2019-02-21 15:24:42 +03: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-07-20 12:48:24 +03:00
|
|
|
use std::{fmt, iter::successors, ops::RangeInclusive};
|
2019-01-25 02:09:31 +03:00
|
|
|
|
2019-02-23 16:55:01 +03:00
|
|
|
use ra_parser::ParseError;
|
2019-07-18 19:23:05 +03:00
|
|
|
use rowan::GreenNodeBuilder;
|
2018-08-10 17:49:45 +03:00
|
|
|
|
2019-02-20 16:16:14 +03:00
|
|
|
use crate::{
|
2019-02-23 16:55:01 +03:00
|
|
|
syntax_error::{SyntaxError, SyntaxErrorKind},
|
2019-07-18 23:19:04 +03:00
|
|
|
AstNode, Parse, SmolStr, SourceFile, SyntaxKind, SyntaxNodePtr, SyntaxText, TextRange,
|
|
|
|
TextUnit,
|
2019-02-20 16:16:14 +03:00
|
|
|
};
|
|
|
|
|
2019-01-07 16:15:47 +03:00
|
|
|
pub use rowan::WalkEvent;
|
2019-04-09 01:06:30 +03:00
|
|
|
pub(crate) use rowan::{GreenNode, GreenToken};
|
2019-02-21 16:12:15 +03:00
|
|
|
|
2019-04-22 00:52:21 +03:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
2019-04-21 17:47:55 +03:00
|
|
|
pub enum InsertPosition<T> {
|
|
|
|
First,
|
|
|
|
Last,
|
|
|
|
Before(T),
|
|
|
|
After(T),
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
|
|
|
pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode);
|
2018-10-02 18:14:33 +03:00
|
|
|
|
2019-02-21 16:04:03 +03:00
|
|
|
impl fmt::Debug for SyntaxNode {
|
2019-07-20 12:48:24 +03:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
if f.alternate() {
|
|
|
|
let mut level = 0;
|
|
|
|
for event in self.preorder_with_tokens() {
|
|
|
|
match event {
|
|
|
|
WalkEvent::Enter(element) => {
|
|
|
|
for _ in 0..level {
|
|
|
|
write!(f, " ")?;
|
|
|
|
}
|
|
|
|
match element {
|
|
|
|
SyntaxElement::Node(node) => writeln!(f, "{:?}", node)?,
|
|
|
|
SyntaxElement::Token(token) => writeln!(f, "{:?}", token)?,
|
|
|
|
}
|
|
|
|
level += 1;
|
|
|
|
}
|
|
|
|
WalkEvent::Leave(_) => level -= 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_eq!(level, 0);
|
|
|
|
Ok(())
|
|
|
|
} else {
|
2019-07-20 12:58:27 +03:00
|
|
|
write!(f, "{:?}@{:?}", self.kind(), self.text_range())
|
2019-07-20 12:48:24 +03:00
|
|
|
}
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SyntaxNode {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::Display::fmt(&self.text(), fmt)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-02 18:14:33 +03:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum Direction {
|
|
|
|
Next,
|
|
|
|
Prev,
|
|
|
|
}
|
|
|
|
|
2019-01-07 16:15:47 +03:00
|
|
|
impl SyntaxNode {
|
2019-07-18 19:23:05 +03:00
|
|
|
pub(crate) fn new(green: GreenNode) -> SyntaxNode {
|
|
|
|
let inner = rowan::cursor::SyntaxNode::new_root(green);
|
|
|
|
SyntaxNode(inner)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
2019-04-09 01:06:30 +03:00
|
|
|
self.0.kind().0.into()
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-07-20 12:58:27 +03:00
|
|
|
pub fn text_range(&self) -> TextRange {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.text_range()
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn text(&self) -> SyntaxText {
|
2019-07-19 21:41:36 +03:00
|
|
|
SyntaxText::new(self.clone())
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn parent(&self) -> Option<SyntaxNode> {
|
|
|
|
self.0.parent().map(SyntaxNode)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn first_child(&self) -> Option<SyntaxNode> {
|
|
|
|
self.0.first_child().map(SyntaxNode)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.first_child_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn last_child(&self) -> Option<SyntaxNode> {
|
|
|
|
self.0.last_child().map(SyntaxNode)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.last_child_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn next_sibling(&self) -> Option<SyntaxNode> {
|
|
|
|
self.0.next_sibling().map(SyntaxNode)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.next_sibling_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn prev_sibling(&self) -> Option<SyntaxNode> {
|
|
|
|
self.0.prev_sibling().map(SyntaxNode)
|
2019-02-21 16:04:03 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.prev_sibling_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-02-21 16:04:03 +03:00
|
|
|
pub fn children(&self) -> SyntaxNodeChildren {
|
|
|
|
SyntaxNodeChildren(self.0.children())
|
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn children_with_tokens(&self) -> SyntaxElementChildren {
|
|
|
|
SyntaxElementChildren(self.0.children_with_tokens())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn first_token(&self) -> Option<SyntaxToken> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.first_token().map(SyntaxToken)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn last_token(&self) -> Option<SyntaxToken> {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.last_token().map(SyntaxToken)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
|
|
|
|
successors(Some(self.clone()), |node| node.parent())
|
2018-10-02 18:02:57 +03:00
|
|
|
}
|
2019-02-21 16:04:03 +03:00
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
|
2018-10-17 19:52:25 +03:00
|
|
|
self.preorder().filter_map(|event| match event {
|
|
|
|
WalkEvent::Enter(node) => Some(node),
|
|
|
|
WalkEvent::Leave(_) => None,
|
2018-10-02 18:02:57 +03:00
|
|
|
})
|
|
|
|
}
|
2019-02-21 16:04:03 +03:00
|
|
|
|
2019-03-30 13:25:53 +03: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-07-18 19:23:05 +03:00
|
|
|
pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = SyntaxNode> {
|
|
|
|
successors(Some(self.clone()), move |node| match direction {
|
2018-10-02 18:14:33 +03:00
|
|
|
Direction::Next => node.next_sibling(),
|
|
|
|
Direction::Prev => node.prev_sibling(),
|
|
|
|
})
|
|
|
|
}
|
2019-02-21 16:04:03 +03:00
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn siblings_with_tokens(
|
|
|
|
&self,
|
|
|
|
direction: Direction,
|
|
|
|
) -> impl Iterator<Item = SyntaxElement> {
|
2019-07-18 19:23:05 +03:00
|
|
|
let me: SyntaxElement = self.clone().into();
|
2019-04-13 16:43:49 +02:00
|
|
|
successors(Some(me), move |el| match direction {
|
2019-03-30 13:25:53 +03:00
|
|
|
Direction::Next => el.next_sibling_or_token(),
|
|
|
|
Direction::Prev => el.prev_sibling_or_token(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<SyntaxNode>> {
|
2018-10-17 19:52:25 +03:00
|
|
|
self.0.preorder().map(|event| match event {
|
2019-07-18 19:23:05 +03:00
|
|
|
WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode(n)),
|
|
|
|
WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode(n)),
|
2018-10-17 19:52:25 +03:00
|
|
|
})
|
|
|
|
}
|
2019-02-21 15:51:22 +03:00
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<SyntaxElement>> {
|
|
|
|
self.0.preorder_with_tokens().map(|event| match event {
|
2019-07-18 19:23:05 +03:00
|
|
|
WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxElement::new(n)),
|
|
|
|
WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxElement::new(n)),
|
2019-03-30 13:25:53 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-10-02 17:07:12 +03:00
|
|
|
pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
|
2019-03-30 13:25:53 +03:00
|
|
|
self.0.replace_with(replacement)
|
|
|
|
}
|
2019-04-21 17:47:55 +03:00
|
|
|
|
|
|
|
/// Adds specified children (tokens or nodes) to the current node at the
|
|
|
|
/// specific position.
|
|
|
|
///
|
|
|
|
/// This is a type-unsafe low-level editing API, if you need to use it,
|
|
|
|
/// prefer to create a type-safe abstraction on top of it instead.
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn insert_children(
|
2019-04-21 17:47:55 +03:00
|
|
|
&self,
|
2019-07-18 19:23:05 +03:00
|
|
|
position: InsertPosition<SyntaxElement>,
|
|
|
|
to_insert: impl Iterator<Item = SyntaxElement>,
|
|
|
|
) -> SyntaxNode {
|
2019-04-21 17:47:55 +03:00
|
|
|
let mut delta = TextUnit::default();
|
|
|
|
let to_insert = to_insert.map(|element| {
|
|
|
|
delta += element.text_len();
|
|
|
|
to_green_element(element)
|
|
|
|
});
|
|
|
|
|
|
|
|
let old_children = self.0.green().children();
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
let new_children = match &position {
|
2019-04-21 17:47:55 +03:00
|
|
|
InsertPosition::First => {
|
|
|
|
to_insert.chain(old_children.iter().cloned()).collect::<Box<[_]>>()
|
|
|
|
}
|
|
|
|
InsertPosition::Last => {
|
|
|
|
old_children.iter().cloned().chain(to_insert).collect::<Box<[_]>>()
|
|
|
|
}
|
|
|
|
InsertPosition::Before(anchor) | InsertPosition::After(anchor) => {
|
|
|
|
let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 };
|
2019-07-18 19:23:05 +03:00
|
|
|
let split_at = self.position_of_child(anchor.clone()) + take_anchor;
|
2019-04-22 13:01:33 +03:00
|
|
|
let (before, after) = old_children.split_at(split_at);
|
2019-04-21 17:47:55 +03:00
|
|
|
before
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.chain(to_insert)
|
|
|
|
.chain(after.iter().cloned())
|
|
|
|
.collect::<Box<[_]>>()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-04-22 13:01:33 +03:00
|
|
|
self.with_children(new_children)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Replaces all nodes in `to_delete` with nodes from `to_insert`
|
|
|
|
///
|
|
|
|
/// This is a type-unsafe low-level editing API, if you need to use it,
|
|
|
|
/// prefer to create a type-safe abstraction on top of it instead.
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn replace_children(
|
2019-04-22 13:01:33 +03:00
|
|
|
&self,
|
2019-07-18 19:23:05 +03:00
|
|
|
to_delete: RangeInclusive<SyntaxElement>,
|
|
|
|
to_insert: impl Iterator<Item = SyntaxElement>,
|
|
|
|
) -> SyntaxNode {
|
|
|
|
let start = self.position_of_child(to_delete.start().clone());
|
|
|
|
let end = self.position_of_child(to_delete.end().clone());
|
2019-04-22 13:01:33 +03:00
|
|
|
let old_children = self.0.green().children();
|
|
|
|
|
|
|
|
let new_children = old_children[..start]
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.chain(to_insert.map(to_green_element))
|
|
|
|
.chain(old_children[end + 1..].iter().cloned())
|
|
|
|
.collect::<Box<[_]>>();
|
|
|
|
self.with_children(new_children)
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
fn with_children(&self, new_children: Box<[rowan::GreenElement]>) -> SyntaxNode {
|
2019-04-22 13:01:33 +03:00
|
|
|
let len = new_children.iter().map(|it| it.text_len()).sum::<TextUnit>();
|
2019-04-21 17:47:55 +03:00
|
|
|
let new_node = GreenNode::new(rowan::SyntaxKind(self.kind() as u16), new_children);
|
|
|
|
let new_file_node = self.replace_with(new_node);
|
2019-05-28 16:34:23 +03:00
|
|
|
let file = SourceFile::new(new_file_node);
|
2019-04-21 17:47:55 +03:00
|
|
|
|
|
|
|
// FIXME: use a more elegant way to re-fetch the node (#1185), make
|
|
|
|
// `range` private afterwards
|
|
|
|
let mut ptr = SyntaxNodePtr::new(self);
|
2019-04-22 13:01:33 +03:00
|
|
|
ptr.range = TextRange::offset_len(ptr.range().start(), len);
|
2019-07-04 13:26:44 -04:00
|
|
|
ptr.to_node(file.syntax()).to_owned()
|
2019-04-22 13:01:33 +03:00
|
|
|
}
|
2019-04-21 17:47:55 +03:00
|
|
|
|
2019-04-22 13:01:33 +03:00
|
|
|
fn position_of_child(&self, child: SyntaxElement) -> usize {
|
|
|
|
self.children_with_tokens()
|
|
|
|
.position(|it| it == child)
|
2019-07-18 19:23:05 +03:00
|
|
|
.expect("element is not a child of current element")
|
2019-04-22 13:01:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_green_element(element: SyntaxElement) -> rowan::GreenElement {
|
|
|
|
match element {
|
|
|
|
SyntaxElement::Node(node) => node.0.green().clone().into(),
|
|
|
|
SyntaxElement::Token(tok) => {
|
|
|
|
GreenToken::new(rowan::SyntaxKind(tok.kind() as u16), tok.text().clone()).into()
|
2019-04-21 17:47:55 +03:00
|
|
|
}
|
|
|
|
}
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct SyntaxToken(pub(crate) rowan::cursor::SyntaxToken);
|
2019-03-30 13:25:53 +03:00
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl fmt::Debug for SyntaxToken {
|
2019-03-30 13:25:53 +03:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
2019-07-20 12:58:27 +03:00
|
|
|
write!(fmt, "{:?}@{:?}", self.kind(), self.text_range())?;
|
2019-04-02 14:04:23 +03:00
|
|
|
if self.text().len() < 25 {
|
|
|
|
return write!(fmt, " {:?}", self.text());
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
2019-04-02 14:04:23 +03: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 13:25:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl fmt::Display for SyntaxToken {
|
2019-03-30 13:25:53 +03:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::Display::fmt(self.text(), fmt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl SyntaxToken {
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
2019-04-09 01:06:30 +03:00
|
|
|
self.0.kind().0.into()
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn text(&self) -> &SmolStr {
|
2019-03-30 13:25:53 +03:00
|
|
|
self.0.text()
|
|
|
|
}
|
|
|
|
|
2019-07-20 12:58:27 +03:00
|
|
|
pub fn text_range(&self) -> TextRange {
|
2019-07-18 19:23:05 +03:00
|
|
|
self.0.text_range()
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn parent(&self) -> SyntaxNode {
|
|
|
|
SyntaxNode(self.0.parent())
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.next_sibling_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
|
|
|
|
self.0.prev_sibling_or_token().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn siblings_with_tokens(
|
|
|
|
&self,
|
|
|
|
direction: Direction,
|
2019-07-18 19:23:05 +03:00
|
|
|
) -> impl Iterator<Item = SyntaxElement> {
|
|
|
|
let me: SyntaxElement = self.clone().into();
|
2019-04-13 16:43:49 +02:00
|
|
|
successors(Some(me), move |el| match direction {
|
2019-03-30 13:25:53 +03:00
|
|
|
Direction::Next => el.next_sibling_or_token(),
|
|
|
|
Direction::Prev => el.prev_sibling_or_token(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn next_token(&self) -> Option<SyntaxToken> {
|
|
|
|
self.0.next_token().map(SyntaxToken)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn prev_token(&self) -> Option<SyntaxToken> {
|
|
|
|
self.0.prev_token().map(SyntaxToken)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode {
|
|
|
|
self.0.replace_with(new_token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
|
|
|
pub enum SyntaxElement {
|
|
|
|
Node(SyntaxNode),
|
|
|
|
Token(SyntaxToken),
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl From<SyntaxNode> for SyntaxElement {
|
|
|
|
fn from(node: SyntaxNode) -> Self {
|
|
|
|
SyntaxElement::Node(node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SyntaxToken> for SyntaxElement {
|
|
|
|
fn from(token: SyntaxToken) -> Self {
|
|
|
|
SyntaxElement::Token(token)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SyntaxElement {
|
2019-03-30 13:25:53 +03:00
|
|
|
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),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl SyntaxElement {
|
|
|
|
pub(crate) fn new(el: rowan::cursor::SyntaxElement) -> Self {
|
|
|
|
match el {
|
|
|
|
rowan::cursor::SyntaxElement::Node(it) => SyntaxElement::Node(SyntaxNode(it)),
|
|
|
|
rowan::cursor::SyntaxElement::Token(it) => SyntaxElement::Token(SyntaxToken(it)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn kind(&self) -> SyntaxKind {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.kind(),
|
|
|
|
SyntaxElement::Token(it) => it.kind(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn as_node(&self) -> Option<&SyntaxNode> {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
2019-07-18 19:23:05 +03:00
|
|
|
SyntaxElement::Node(node) => Some(node),
|
2019-03-30 13:25:53 +03:00
|
|
|
SyntaxElement::Token(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 19:05:34 +03:00
|
|
|
pub fn into_node(self) -> Option<SyntaxNode> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(node) => Some(node),
|
|
|
|
SyntaxElement::Token(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn as_token(&self) -> Option<&SyntaxToken> {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(_) => None,
|
2019-07-18 19:23:05 +03:00
|
|
|
SyntaxElement::Token(token) => Some(token),
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 19:05:34 +03:00
|
|
|
pub fn into_token(self) -> Option<SyntaxToken> {
|
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(_) => None,
|
|
|
|
SyntaxElement::Token(token) => Some(token),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.next_sibling_or_token(),
|
|
|
|
SyntaxElement::Token(it) => it.next_sibling_or_token(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
|
|
|
SyntaxElement::Node(it) => it.prev_sibling_or_token(),
|
|
|
|
SyntaxElement::Token(it) => it.prev_sibling_or_token(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
2019-07-18 19:23:05 +03:00
|
|
|
SyntaxElement::Node(it) => it.clone(),
|
2019-03-30 13:25:53 +03:00
|
|
|
SyntaxElement::Token(it) => it.parent(),
|
|
|
|
}
|
|
|
|
.ancestors()
|
|
|
|
}
|
2019-04-21 17:47:55 +03:00
|
|
|
|
2019-07-20 12:58:27 +03:00
|
|
|
pub fn text_range(&self) -> TextRange {
|
2019-04-21 17:47:55 +03:00
|
|
|
match self {
|
2019-07-20 12:58:27 +03:00
|
|
|
SyntaxElement::Node(it) => it.text_range(),
|
|
|
|
SyntaxElement::Token(it) => it.text_range(),
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
fn text_len(&self) -> TextUnit {
|
2019-03-30 13:25:53 +03:00
|
|
|
match self {
|
2019-07-18 19:23:05 +03:00
|
|
|
SyntaxElement::Node(node) => node.0.green().text_len(),
|
|
|
|
SyntaxElement::Token(token) => TextUnit::of_str(token.0.text()),
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
2018-10-02 17:07:12 +03:00
|
|
|
}
|
2018-08-10 17:49:45 +03:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct SyntaxNodeChildren(rowan::cursor::SyntaxNodeChildren);
|
2018-08-10 17:49:45 +03:00
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl Iterator for SyntaxNodeChildren {
|
|
|
|
type Item = SyntaxNode;
|
|
|
|
fn next(&mut self) -> Option<SyntaxNode> {
|
|
|
|
self.0.next().map(SyntaxNode)
|
2018-08-10 17:49:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct SyntaxElementChildren(rowan::cursor::SyntaxElementChildren);
|
2019-03-30 13:25:53 +03:00
|
|
|
|
2019-07-18 19:23:05 +03:00
|
|
|
impl Iterator for SyntaxElementChildren {
|
|
|
|
type Item = SyntaxElement;
|
|
|
|
fn next(&mut self) -> Option<SyntaxElement> {
|
|
|
|
self.0.next().map(SyntaxElement::new)
|
2019-03-30 13:25:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-23 16:55:01 +03:00
|
|
|
pub struct SyntaxTreeBuilder {
|
|
|
|
errors: Vec<SyntaxError>,
|
2019-04-09 01:06:30 +03:00
|
|
|
inner: GreenNodeBuilder,
|
2019-02-23 16:55:01 +03: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)
|
|
|
|
}
|
|
|
|
|
2019-07-18 23:19:04 +03:00
|
|
|
pub fn finish(self) -> Parse<SyntaxNode> {
|
2019-05-05 11:34:39 +03:00
|
|
|
let (green, errors) = self.finish_raw();
|
2019-05-05 11:33:07 +03:00
|
|
|
let node = SyntaxNode::new(green);
|
2019-02-23 16:55:01 +03:00
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
crate::validation::validate_block_structure(&node);
|
|
|
|
}
|
2019-07-18 19:23:05 +03:00
|
|
|
Parse::new(node.0.green().clone(), errors)
|
2019-02-23 16:55:01 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
|
2019-04-09 01:06:30 +03:00
|
|
|
self.inner.token(rowan::SyntaxKind(kind.into()), text)
|
2019-02-23 16:55:01 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn start_node(&mut self, kind: SyntaxKind) {
|
2019-04-09 01:06:30 +03:00
|
|
|
self.inner.start_node(rowan::SyntaxKind(kind.into()))
|
2019-02-23 16:55:01 +03:00
|
|
|
}
|
|
|
|
|
2019-03-30 13:25:53 +03:00
|
|
|
pub fn finish_node(&mut self) {
|
|
|
|
self.inner.finish_node()
|
2019-02-23 16:55:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
|
|
|
|
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
|
|
|
|
self.errors.push(error)
|
|
|
|
}
|
|
|
|
}
|