2019-02-21 12:24:42 +00:00
|
|
|
//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
|
|
|
|
//!
|
|
|
|
//! The CST includes comments and whitespace, provides a single node type,
|
|
|
|
//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
|
|
|
|
//!
|
|
|
|
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
|
|
|
|
//! modules just wraps its API.
|
|
|
|
|
2019-02-21 13:12:15 +00:00
|
|
|
use std::{
|
|
|
|
fmt::{self, Write},
|
2019-04-08 22:06:30 +00:00
|
|
|
any::Any,
|
2019-02-21 13:12:15 +00:00
|
|
|
borrow::Borrow,
|
|
|
|
};
|
2019-01-24 23:09:31 +00:00
|
|
|
|
2019-02-23 13:55:01 +00:00
|
|
|
use ra_parser::ParseError;
|
2019-04-08 22:06:30 +00:00
|
|
|
use rowan::{TransparentNewType, GreenNodeBuilder};
|
2018-08-10 14:49:45 +00:00
|
|
|
|
2019-02-20 13:16:14 +00:00
|
|
|
use crate::{
|
2019-02-23 13:55:01 +00:00
|
|
|
SmolStr, SyntaxKind, TextUnit, TextRange, SyntaxText, SourceFile, AstNode,
|
|
|
|
syntax_error::{SyntaxError, SyntaxErrorKind},
|
2019-02-20 13:16:14 +00:00
|
|
|
};
|
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
pub use rowan::WalkEvent;
|
2019-04-08 22:06:30 +00:00
|
|
|
pub(crate) use rowan::{GreenNode, GreenToken};
|
2019-02-21 13:12:15 +00:00
|
|
|
|
|
|
|
/// Marker trait for CST and AST nodes
|
2019-04-08 22:06:30 +00:00
|
|
|
pub trait SyntaxNodeWrapper: TransparentNewType<Repr = rowan::SyntaxNode> {}
|
|
|
|
impl<T: TransparentNewType<Repr = rowan::SyntaxNode>> SyntaxNodeWrapper for T {}
|
2019-01-07 13:42:10 +00:00
|
|
|
|
2019-02-21 13:12:15 +00:00
|
|
|
/// An owning smart pointer for CST or AST node.
|
2019-01-07 14:00:39 +00:00
|
|
|
#[derive(PartialEq, Eq, Hash)]
|
2019-04-08 22:06:30 +00:00
|
|
|
pub struct TreeArc<T: SyntaxNodeWrapper>(pub(crate) rowan::TreeArc<T>);
|
2019-01-07 13:42:10 +00:00
|
|
|
|
2019-02-21 13:12:15 +00:00
|
|
|
impl<T: SyntaxNodeWrapper> Borrow<T> for TreeArc<T> {
|
2019-01-24 23:09:31 +00:00
|
|
|
fn borrow(&self) -> &T {
|
|
|
|
&*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:59:06 +00:00
|
|
|
impl<T> TreeArc<T>
|
2019-01-07 13:42:10 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
T: SyntaxNodeWrapper,
|
2019-01-07 13:42:10 +00:00
|
|
|
{
|
2019-01-11 16:59:06 +00:00
|
|
|
pub(crate) fn cast<U>(this: TreeArc<T>) -> TreeArc<U>
|
2019-01-07 13:42:10 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
U: SyntaxNodeWrapper,
|
2019-01-07 13:42:10 +00:00
|
|
|
{
|
2019-01-11 16:59:06 +00:00
|
|
|
TreeArc(rowan::TreeArc::cast(this.0))
|
2019-01-07 13:42:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:59:06 +00:00
|
|
|
impl<T> std::ops::Deref for TreeArc<T>
|
2019-01-07 13:42:10 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
T: SyntaxNodeWrapper,
|
2019-01-07 13:42:10 +00:00
|
|
|
{
|
|
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &T {
|
|
|
|
self.0.deref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:59:06 +00:00
|
|
|
impl<T> PartialEq<T> for TreeArc<T>
|
2019-01-08 08:28:42 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
T: SyntaxNodeWrapper,
|
2019-01-08 08:28:42 +00:00
|
|
|
T: PartialEq<T>,
|
|
|
|
{
|
|
|
|
fn eq(&self, other: &T) -> bool {
|
|
|
|
let t: &T = self;
|
|
|
|
t == other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:59:06 +00:00
|
|
|
impl<T> Clone for TreeArc<T>
|
2019-01-07 14:00:39 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
T: SyntaxNodeWrapper,
|
2019-01-07 14:00:39 +00:00
|
|
|
{
|
2019-01-11 16:59:06 +00:00
|
|
|
fn clone(&self) -> TreeArc<T> {
|
|
|
|
TreeArc(self.0.clone())
|
2019-01-07 14:00:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:59:06 +00:00
|
|
|
impl<T> fmt::Debug for TreeArc<T>
|
2019-01-07 13:42:10 +00:00
|
|
|
where
|
2019-02-21 13:12:15 +00:00
|
|
|
T: SyntaxNodeWrapper,
|
2019-01-07 13:42:10 +00:00
|
|
|
T: fmt::Debug,
|
|
|
|
{
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::Debug::fmt(&self.0, fmt)
|
|
|
|
}
|
|
|
|
}
|
2018-08-17 18:10:55 +00:00
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
#[derive(PartialEq, Eq, Hash)]
|
|
|
|
#[repr(transparent)]
|
2019-04-08 22:06:30 +00:00
|
|
|
pub struct SyntaxNode(pub(crate) rowan::SyntaxNode);
|
2019-01-07 13:15:47 +00:00
|
|
|
unsafe impl TransparentNewType for SyntaxNode {
|
2019-04-08 22:06:30 +00:00
|
|
|
type Repr = rowan::SyntaxNode;
|
2018-10-02 14:07:12 +00:00
|
|
|
}
|
2018-08-17 18:10:55 +00:00
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
impl ToOwned for SyntaxNode {
|
|
|
|
type Owned = TreeArc<SyntaxNode>;
|
|
|
|
fn to_owned(&self) -> TreeArc<SyntaxNode> {
|
|
|
|
let ptr = TreeArc(self.0.to_owned());
|
2019-01-11 16:59:06 +00:00
|
|
|
TreeArc::cast(ptr)
|
2018-10-02 14:07:12 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-02 15:14:33 +00:00
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
impl fmt::Debug for SyntaxNode {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
2019-03-30 10:25:53 +00:00
|
|
|
write!(fmt, "{:?}@{:?}", self.kind(), self.range())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SyntaxNode {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::Display::fmt(&self.text(), fmt)
|
2019-02-21 13:04:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-02 15:14:33 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum Direction {
|
|
|
|
Next,
|
|
|
|
Prev,
|
|
|
|
}
|
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
impl SyntaxNode {
|
2019-02-21 13:04:03 +00:00
|
|
|
pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SyntaxNode> {
|
2019-04-08 22:06:30 +00:00
|
|
|
let errors: Option<Box<Any + Send + Sync>> =
|
|
|
|
if errors.is_empty() { None } else { Some(Box::new(errors)) };
|
2019-02-21 13:04:03 +00:00
|
|
|
let ptr = TreeArc(rowan::SyntaxNode::new(green, errors));
|
|
|
|
TreeArc::cast(ptr)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
2019-04-08 22:06:30 +00:00
|
|
|
self.0.kind().0.into()
|
2019-02-21 13:04:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn range(&self) -> TextRange {
|
|
|
|
self.0.range()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn text(&self) -> SyntaxText {
|
|
|
|
SyntaxText::new(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(&self) -> Option<&SyntaxNode> {
|
|
|
|
self.0.parent().map(SyntaxNode::from_repr)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn first_child(&self) -> Option<&SyntaxNode> {
|
|
|
|
self.0.first_child().map(SyntaxNode::from_repr)
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.first_child_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
pub fn last_child(&self) -> Option<&SyntaxNode> {
|
|
|
|
self.0.last_child().map(SyntaxNode::from_repr)
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.last_child_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
pub fn next_sibling(&self) -> Option<&SyntaxNode> {
|
|
|
|
self.0.next_sibling().map(SyntaxNode::from_repr)
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.next_sibling_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
pub fn prev_sibling(&self) -> Option<&SyntaxNode> {
|
|
|
|
self.0.prev_sibling().map(SyntaxNode::from_repr)
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.prev_sibling_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
pub fn children(&self) -> SyntaxNodeChildren {
|
|
|
|
SyntaxNodeChildren(self.0.children())
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn children_with_tokens(&self) -> SyntaxElementChildren {
|
|
|
|
SyntaxElementChildren(self.0.children_with_tokens())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn first_token(&self) -> Option<SyntaxToken> {
|
|
|
|
self.0.first_token().map(SyntaxToken::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn last_token(&self) -> Option<SyntaxToken> {
|
|
|
|
self.0.last_token().map(SyntaxToken::from)
|
|
|
|
}
|
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> {
|
2018-10-15 16:55:32 +00:00
|
|
|
crate::algo::generate(Some(self), |&node| node.parent())
|
2018-10-02 15:02:57 +00:00
|
|
|
}
|
2019-02-21 13:04:03 +00:00
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
pub fn descendants(&self) -> impl Iterator<Item = &SyntaxNode> {
|
2018-10-17 16:52:25 +00:00
|
|
|
self.preorder().filter_map(|event| match event {
|
|
|
|
WalkEvent::Enter(node) => Some(node),
|
|
|
|
WalkEvent::Leave(_) => None,
|
2018-10-02 15:02:57 +00:00
|
|
|
})
|
|
|
|
}
|
2019-02-21 13:04:03 +00:00
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn descendants_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
|
|
|
|
self.preorder_with_tokens().filter_map(|event| match event {
|
|
|
|
WalkEvent::Enter(it) => Some(it),
|
|
|
|
WalkEvent::Leave(_) => None,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> {
|
2018-10-15 16:55:32 +00:00
|
|
|
crate::algo::generate(Some(self), move |&node| match direction {
|
2018-10-02 15:14:33 +00:00
|
|
|
Direction::Next => node.next_sibling(),
|
|
|
|
Direction::Prev => node.prev_sibling(),
|
|
|
|
})
|
|
|
|
}
|
2019-02-21 13:04:03 +00:00
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn siblings_with_tokens(
|
|
|
|
&self,
|
|
|
|
direction: Direction,
|
|
|
|
) -> impl Iterator<Item = SyntaxElement> {
|
|
|
|
let me: SyntaxElement = self.into();
|
|
|
|
crate::algo::generate(Some(me), move |el| match direction {
|
|
|
|
Direction::Next => el.next_sibling_or_token(),
|
|
|
|
Direction::Prev => el.prev_sibling_or_token(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> {
|
2018-10-17 16:52:25 +00:00
|
|
|
self.0.preorder().map(|event| match event {
|
2019-01-07 13:15:47 +00:00
|
|
|
WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)),
|
|
|
|
WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)),
|
2018-10-17 16:52:25 +00:00
|
|
|
})
|
|
|
|
}
|
2019-02-21 12:51:22 +00:00
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<SyntaxElement>> {
|
|
|
|
self.0.preorder_with_tokens().map(|event| match event {
|
|
|
|
WalkEvent::Enter(n) => WalkEvent::Enter(n.into()),
|
|
|
|
WalkEvent::Leave(n) => WalkEvent::Leave(n.into()),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-21 13:04:03 +00:00
|
|
|
pub fn memory_size_of_subtree(&self) -> usize {
|
|
|
|
self.0.memory_size_of_subtree()
|
|
|
|
}
|
|
|
|
|
2019-02-21 12:51:22 +00:00
|
|
|
pub fn debug_dump(&self) -> String {
|
|
|
|
let mut errors: Vec<_> = match self.ancestors().find_map(SourceFile::cast) {
|
|
|
|
Some(file) => file.errors(),
|
|
|
|
None => self.root_data().to_vec(),
|
|
|
|
};
|
|
|
|
errors.sort_by_key(|e| e.offset());
|
|
|
|
let mut err_pos = 0;
|
|
|
|
let mut level = 0;
|
|
|
|
let mut buf = String::new();
|
|
|
|
macro_rules! indent {
|
|
|
|
() => {
|
|
|
|
for _ in 0..level {
|
|
|
|
buf.push_str(" ");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
for event in self.preorder_with_tokens() {
|
2019-02-21 12:51:22 +00:00
|
|
|
match event {
|
2019-03-30 10:25:53 +00:00
|
|
|
WalkEvent::Enter(element) => {
|
2019-02-21 12:51:22 +00:00
|
|
|
indent!();
|
2019-03-30 10:25:53 +00:00
|
|
|
match element {
|
|
|
|
SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(),
|
|
|
|
SyntaxElement::Token(token) => {
|
|
|
|
writeln!(buf, "{:?}", token).unwrap();
|
|
|
|
let off = token.range().end();
|
|
|
|
while err_pos < errors.len() && errors[err_pos].offset() <= off {
|
|
|
|
indent!();
|
|
|
|
writeln!(buf, "err: `{}`", errors[err_pos]).unwrap();
|
|
|
|
err_pos += 1;
|
|
|
|
}
|
2019-02-21 12:51:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
level += 1;
|
|
|
|
}
|
|
|
|
WalkEvent::Leave(_) => level -= 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(level, 0);
|
|
|
|
for err in errors[err_pos..].iter() {
|
|
|
|
writeln!(buf, "err: `{}`", err).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
buf
|
|
|
|
}
|
2018-08-17 18:10:55 +00:00
|
|
|
|
2019-04-08 22:06:30 +00:00
|
|
|
pub(crate) fn root_data(&self) -> &[SyntaxError] {
|
|
|
|
match self.0.root_data() {
|
|
|
|
None => &[],
|
|
|
|
Some(data) => {
|
|
|
|
let data: &Vec<SyntaxError> = std::any::Any::downcast_ref(data).unwrap();
|
|
|
|
data.as_slice()
|
|
|
|
}
|
|
|
|
}
|
2018-10-02 14:07:12 +00:00
|
|
|
}
|
2019-01-10 15:03:15 +00:00
|
|
|
|
2018-10-02 14:07:12 +00:00
|
|
|
pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
|
2019-03-30 10:25:53 +00:00
|
|
|
self.0.replace_with(replacement)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
2019-04-08 22:06:30 +00:00
|
|
|
pub struct SyntaxToken<'a>(pub(crate) rowan::SyntaxToken<'a>);
|
2019-03-30 10:25:53 +00:00
|
|
|
|
|
|
|
//FIXME: always output text
|
|
|
|
impl<'a> fmt::Debug for SyntaxToken<'a> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
|
2019-04-02 11:04:23 +00:00
|
|
|
if self.text().len() < 25 {
|
|
|
|
return write!(fmt, " {:?}", self.text());
|
2019-03-30 10:25:53 +00:00
|
|
|
}
|
2019-04-02 11:04:23 +00:00
|
|
|
let text = self.text().as_str();
|
|
|
|
for idx in 21..25 {
|
|
|
|
if text.is_char_boundary(idx) {
|
|
|
|
let text = format!("{} ...", &text[..idx]);
|
|
|
|
return write!(fmt, " {:?}", text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unreachable!()
|
2019-03-30 10:25:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> fmt::Display for SyntaxToken<'a> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::Display::fmt(self.text(), fmt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-08 22:06:30 +00:00
|
|
|
impl<'a> From<rowan::SyntaxToken<'a>> for SyntaxToken<'a> {
|
|
|
|
fn from(t: rowan::SyntaxToken<'a>) -> Self {
|
2019-03-30 10:25:53 +00:00
|
|
|
SyntaxToken(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SyntaxToken<'a> {
|
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
2019-04-08 22:06:30 +00:00
|
|
|
self.0.kind().0.into()
|
2019-03-30 10:25:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn text(&self) -> &'a SmolStr {
|
|
|
|
self.0.text()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn range(&self) -> TextRange {
|
|
|
|
self.0.range()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(&self) -> &'a SyntaxNode {
|
|
|
|
SyntaxNode::from_repr(self.0.parent())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
|
|
|
|
self.0.next_sibling_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
|
|
|
|
self.0.prev_sibling_or_token().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn siblings_with_tokens(
|
|
|
|
&self,
|
|
|
|
direction: Direction,
|
|
|
|
) -> impl Iterator<Item = SyntaxElement<'a>> {
|
|
|
|
let me: SyntaxElement = (*self).into();
|
|
|
|
crate::algo::generate(Some(me), move |el| match direction {
|
|
|
|
Direction::Next => el.next_sibling_or_token(),
|
|
|
|
Direction::Prev => el.prev_sibling_or_token(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_token(&self) -> Option<SyntaxToken<'a>> {
|
|
|
|
self.0.next_token().map(SyntaxToken::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn prev_token(&self) -> Option<SyntaxToken<'a>> {
|
|
|
|
self.0.prev_token().map(SyntaxToken::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode {
|
|
|
|
self.0.replace_with(new_token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
|
|
|
pub enum SyntaxElement<'a> {
|
|
|
|
Node(&'a SyntaxNode),
|
|
|
|
Token(SyntaxToken<'a>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> fmt::Display for SyntaxElement<'a> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => fmt::Display::fmt(it, fmt),
|
|
|
|
SyntaxElement::Token(it) => fmt::Display::fmt(it, fmt),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SyntaxElement<'a> {
|
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.kind(),
|
|
|
|
SyntaxElement::Token(it) => it.kind(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_node(&self) -> Option<&'a SyntaxNode> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(node) => Some(*node),
|
|
|
|
SyntaxElement::Token(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_token(&self) -> Option<SyntaxToken<'a>> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(_) => None,
|
|
|
|
SyntaxElement::Token(token) => Some(*token),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.next_sibling_or_token(),
|
|
|
|
SyntaxElement::Token(it) => it.next_sibling_or_token(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.prev_sibling_or_token(),
|
|
|
|
SyntaxElement::Token(it) => it.prev_sibling_or_token(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ancestors(&self) -> impl Iterator<Item = &'a SyntaxNode> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it,
|
|
|
|
SyntaxElement::Token(it) => it.parent(),
|
|
|
|
}
|
|
|
|
.ancestors()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-08 22:06:30 +00:00
|
|
|
impl<'a> From<rowan::SyntaxElement<'a>> for SyntaxElement<'a> {
|
|
|
|
fn from(el: rowan::SyntaxElement<'a>) -> Self {
|
2019-03-30 10:25:53 +00:00
|
|
|
match el {
|
|
|
|
rowan::SyntaxElement::Node(n) => SyntaxElement::Node(SyntaxNode::from_repr(n)),
|
|
|
|
rowan::SyntaxElement::Token(t) => SyntaxElement::Token(t.into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a SyntaxNode> for SyntaxElement<'a> {
|
|
|
|
fn from(node: &'a SyntaxNode) -> SyntaxElement<'a> {
|
|
|
|
SyntaxElement::Node(node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<SyntaxToken<'a>> for SyntaxElement<'a> {
|
|
|
|
fn from(token: SyntaxToken<'a>) -> SyntaxElement<'a> {
|
|
|
|
SyntaxElement::Token(token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SyntaxElement<'a> {
|
|
|
|
pub fn range(&self) -> TextRange {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.range(),
|
|
|
|
SyntaxElement::Token(it) => it.range(),
|
|
|
|
}
|
2018-10-02 14:07:12 +00:00
|
|
|
}
|
2018-08-10 14:49:45 +00:00
|
|
|
}
|
|
|
|
|
2018-10-02 14:07:12 +00:00
|
|
|
#[derive(Debug)]
|
2019-04-08 22:06:30 +00:00
|
|
|
pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a>);
|
2018-08-10 14:49:45 +00:00
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
impl<'a> Iterator for SyntaxNodeChildren<'a> {
|
|
|
|
type Item = &'a SyntaxNode;
|
2018-08-10 14:49:45 +00:00
|
|
|
|
2019-01-07 13:15:47 +00:00
|
|
|
fn next(&mut self) -> Option<&'a SyntaxNode> {
|
|
|
|
self.0.next().map(SyntaxNode::from_repr)
|
2018-08-10 14:49:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
#[derive(Debug)]
|
2019-04-08 22:06:30 +00:00
|
|
|
pub struct SyntaxElementChildren<'a>(rowan::SyntaxElementChildren<'a>);
|
2019-03-30 10:25:53 +00:00
|
|
|
|
|
|
|
impl<'a> Iterator for SyntaxElementChildren<'a> {
|
|
|
|
type Item = SyntaxElement<'a>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<SyntaxElement<'a>> {
|
|
|
|
self.0.next().map(SyntaxElement::from)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-23 13:55:01 +00:00
|
|
|
pub struct SyntaxTreeBuilder {
|
|
|
|
errors: Vec<SyntaxError>,
|
2019-04-08 22:06:30 +00:00
|
|
|
inner: GreenNodeBuilder,
|
2019-02-23 13:55:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for SyntaxTreeBuilder {
|
|
|
|
fn default() -> SyntaxTreeBuilder {
|
|
|
|
SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SyntaxTreeBuilder {
|
|
|
|
pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
|
|
|
|
let green = self.inner.finish();
|
|
|
|
(green, self.errors)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn finish(self) -> TreeArc<SyntaxNode> {
|
|
|
|
let (green, errors) = self.finish_raw();
|
|
|
|
let node = SyntaxNode::new(green, errors);
|
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
crate::validation::validate_block_structure(&node);
|
|
|
|
}
|
|
|
|
node
|
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
|
2019-04-08 22:06:30 +00:00
|
|
|
self.inner.token(rowan::SyntaxKind(kind.into()), text)
|
2019-02-23 13:55:01 +00:00
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn start_node(&mut self, kind: SyntaxKind) {
|
2019-04-08 22:06:30 +00:00
|
|
|
self.inner.start_node(rowan::SyntaxKind(kind.into()))
|
2019-02-23 13:55:01 +00:00
|
|
|
}
|
|
|
|
|
2019-03-30 10:25:53 +00:00
|
|
|
pub fn finish_node(&mut self) {
|
|
|
|
self.inner.finish_node()
|
2019-02-23 13:55:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
|
|
|
|
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
|
|
|
|
self.errors.push(error)
|
|
|
|
}
|
|
|
|
}
|