//! 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. use std::{ fmt::{self, Write}, iter::successors, ops::RangeInclusive, }; use ra_parser::ParseError; use rowan::GreenNodeBuilder; use crate::{ syntax_error::{SyntaxError, SyntaxErrorKind}, AstNode, Parse, SmolStr, SourceFile, SyntaxKind, SyntaxNodePtr, SyntaxText, TextRange, TextUnit, }; pub use rowan::WalkEvent; pub(crate) use rowan::{GreenNode, GreenToken}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum InsertPosition { First, Last, Before(T), After(T), } #[derive(PartialEq, Eq, Hash, Clone)] pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode); impl fmt::Debug for SyntaxNode { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 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) } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Direction { Next, Prev, } impl SyntaxNode { pub(crate) fn new(green: GreenNode) -> SyntaxNode { let inner = rowan::cursor::SyntaxNode::new_root(green); SyntaxNode(inner) } pub fn kind(&self) -> SyntaxKind { self.0.kind().0.into() } pub fn range(&self) -> TextRange { self.0.text_range() } pub fn text(&self) -> SyntaxText { SyntaxText::new(self) } pub fn parent(&self) -> Option { self.0.parent().map(SyntaxNode) } pub fn first_child(&self) -> Option { self.0.first_child().map(SyntaxNode) } pub fn first_child_or_token(&self) -> Option { self.0.first_child_or_token().map(SyntaxElement::new) } pub fn last_child(&self) -> Option { self.0.last_child().map(SyntaxNode) } pub fn last_child_or_token(&self) -> Option { self.0.last_child_or_token().map(SyntaxElement::new) } pub fn next_sibling(&self) -> Option { self.0.next_sibling().map(SyntaxNode) } pub fn next_sibling_or_token(&self) -> Option { self.0.next_sibling_or_token().map(SyntaxElement::new) } pub fn prev_sibling(&self) -> Option { self.0.prev_sibling().map(SyntaxNode) } pub fn prev_sibling_or_token(&self) -> Option { self.0.prev_sibling_or_token().map(SyntaxElement::new) } pub fn children(&self) -> SyntaxNodeChildren { SyntaxNodeChildren(self.0.children()) } pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren(self.0.children_with_tokens()) } pub fn first_token(&self) -> Option { self.0.first_token().map(SyntaxToken) } pub fn last_token(&self) -> Option { self.0.last_token().map(SyntaxToken) } pub fn ancestors(&self) -> impl Iterator { successors(Some(self.clone()), |node| node.parent()) } pub fn descendants(&self) -> impl Iterator { self.preorder().filter_map(|event| match event { WalkEvent::Enter(node) => Some(node), WalkEvent::Leave(_) => None, }) } pub fn descendants_with_tokens(&self) -> impl Iterator { self.preorder_with_tokens().filter_map(|event| match event { WalkEvent::Enter(it) => Some(it), WalkEvent::Leave(_) => None, }) } pub fn siblings(&self, direction: Direction) -> impl Iterator { successors(Some(self.clone()), move |node| match direction { Direction::Next => node.next_sibling(), Direction::Prev => node.prev_sibling(), }) } pub fn siblings_with_tokens( &self, direction: Direction, ) -> impl Iterator { let me: SyntaxElement = self.clone().into(); successors(Some(me), move |el| match direction { Direction::Next => el.next_sibling_or_token(), Direction::Prev => el.prev_sibling_or_token(), }) } pub fn preorder(&self) -> impl Iterator> { self.0.preorder().map(|event| match event { WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode(n)), WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode(n)), }) } pub fn preorder_with_tokens(&self) -> impl Iterator> { self.0.preorder_with_tokens().map(|event| match event { WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxElement::new(n)), WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxElement::new(n)), }) } pub fn debug_dump(&self) -> String { let mut level = 0; let mut buf = String::new(); for event in self.preorder_with_tokens() { match event { WalkEvent::Enter(element) => { for _ in 0..level { buf.push_str(" "); } match element { SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(), SyntaxElement::Token(token) => writeln!(buf, "{:?}", token).unwrap(), } level += 1; } WalkEvent::Leave(_) => level -= 1, } } assert_eq!(level, 0); buf } pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { self.0.replace_with(replacement) } /// 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. pub fn insert_children( &self, position: InsertPosition, to_insert: impl Iterator, ) -> SyntaxNode { 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(); let new_children = match &position { InsertPosition::First => { to_insert.chain(old_children.iter().cloned()).collect::>() } InsertPosition::Last => { old_children.iter().cloned().chain(to_insert).collect::>() } InsertPosition::Before(anchor) | InsertPosition::After(anchor) => { let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 }; let split_at = self.position_of_child(anchor.clone()) + take_anchor; let (before, after) = old_children.split_at(split_at); before .iter() .cloned() .chain(to_insert) .chain(after.iter().cloned()) .collect::>() } }; 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. pub fn replace_children( &self, to_delete: RangeInclusive, to_insert: impl Iterator, ) -> SyntaxNode { let start = self.position_of_child(to_delete.start().clone()); let end = self.position_of_child(to_delete.end().clone()); 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::>(); self.with_children(new_children) } fn with_children(&self, new_children: Box<[rowan::GreenElement]>) -> SyntaxNode { let len = new_children.iter().map(|it| it.text_len()).sum::(); let new_node = GreenNode::new(rowan::SyntaxKind(self.kind() as u16), new_children); let new_file_node = self.replace_with(new_node); let file = SourceFile::new(new_file_node); // FIXME: use a more elegant way to re-fetch the node (#1185), make // `range` private afterwards let mut ptr = SyntaxNodePtr::new(self); ptr.range = TextRange::offset_len(ptr.range().start(), len); ptr.to_node(file.syntax()).to_owned() } fn position_of_child(&self, child: SyntaxElement) -> usize { self.children_with_tokens() .position(|it| it == child) .expect("element is not a child of current element") } } 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() } } } #[derive(Clone, PartialEq, Eq, Hash)] pub struct SyntaxToken(pub(crate) rowan::cursor::SyntaxToken); impl fmt::Debug for SyntaxToken { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; if self.text().len() < 25 { return write!(fmt, " {:?}", self.text()); } 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!() } } impl fmt::Display for SyntaxToken { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.text(), fmt) } } impl SyntaxToken { pub fn kind(&self) -> SyntaxKind { self.0.kind().0.into() } pub fn text(&self) -> &SmolStr { self.0.text() } pub fn range(&self) -> TextRange { self.0.text_range() } pub fn parent(&self) -> SyntaxNode { SyntaxNode(self.0.parent()) } pub fn next_sibling_or_token(&self) -> Option { self.0.next_sibling_or_token().map(SyntaxElement::new) } pub fn prev_sibling_or_token(&self) -> Option { self.0.prev_sibling_or_token().map(SyntaxElement::new) } pub fn siblings_with_tokens( &self, direction: Direction, ) -> impl Iterator { let me: SyntaxElement = self.clone().into(); successors(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 { self.0.next_token().map(SyntaxToken) } pub fn prev_token(&self) -> Option { self.0.prev_token().map(SyntaxToken) } pub(crate) fn replace_with(&self, new_token: GreenToken) -> GreenNode { self.0.replace_with(new_token) } } #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum SyntaxElement { Node(SyntaxNode), Token(SyntaxToken), } impl From for SyntaxElement { fn from(node: SyntaxNode) -> Self { SyntaxElement::Node(node) } } impl From for SyntaxElement { fn from(token: SyntaxToken) -> Self { SyntaxElement::Token(token) } } impl fmt::Display for SyntaxElement { 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 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)), } } pub fn kind(&self) -> SyntaxKind { match self { SyntaxElement::Node(it) => it.kind(), SyntaxElement::Token(it) => it.kind(), } } pub fn as_node(&self) -> Option<&SyntaxNode> { match self { SyntaxElement::Node(node) => Some(node), SyntaxElement::Token(_) => None, } } pub fn into_node(self) -> Option { match self { SyntaxElement::Node(node) => Some(node), SyntaxElement::Token(_) => None, } } pub fn as_token(&self) -> Option<&SyntaxToken> { match self { SyntaxElement::Node(_) => None, SyntaxElement::Token(token) => Some(token), } } pub fn into_token(self) -> Option { match self { SyntaxElement::Node(_) => None, SyntaxElement::Token(token) => Some(token), } } pub fn next_sibling_or_token(&self) -> Option { 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 { match self { SyntaxElement::Node(it) => it.prev_sibling_or_token(), SyntaxElement::Token(it) => it.prev_sibling_or_token(), } } pub fn ancestors(&self) -> impl Iterator { match self { SyntaxElement::Node(it) => it.clone(), SyntaxElement::Token(it) => it.parent(), } .ancestors() } pub fn range(&self) -> TextRange { match self { SyntaxElement::Node(it) => it.range(), SyntaxElement::Token(it) => it.range(), } } fn text_len(&self) -> TextUnit { match self { SyntaxElement::Node(node) => node.0.green().text_len(), SyntaxElement::Token(token) => TextUnit::of_str(token.0.text()), } } } #[derive(Clone, Debug)] pub struct SyntaxNodeChildren(rowan::cursor::SyntaxNodeChildren); impl Iterator for SyntaxNodeChildren { type Item = SyntaxNode; fn next(&mut self) -> Option { self.0.next().map(SyntaxNode) } } #[derive(Clone, Debug)] pub struct SyntaxElementChildren(rowan::cursor::SyntaxElementChildren); impl Iterator for SyntaxElementChildren { type Item = SyntaxElement; fn next(&mut self) -> Option { self.0.next().map(SyntaxElement::new) } } pub struct SyntaxTreeBuilder { errors: Vec, inner: GreenNodeBuilder, } impl Default for SyntaxTreeBuilder { fn default() -> SyntaxTreeBuilder { SyntaxTreeBuilder { errors: Vec::new(), inner: GreenNodeBuilder::new() } } } impl SyntaxTreeBuilder { pub(crate) fn finish_raw(self) -> (GreenNode, Vec) { let green = self.inner.finish(); (green, self.errors) } pub fn finish(self) -> Parse { let (green, errors) = self.finish_raw(); let node = SyntaxNode::new(green); if cfg!(debug_assertions) { crate::validation::validate_block_structure(&node); } Parse::new(node.0.green().clone(), errors) } pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { self.inner.token(rowan::SyntaxKind(kind.into()), text) } pub fn start_node(&mut self, kind: SyntaxKind) { self.inner.start_node(rowan::SyntaxKind(kind.into())) } pub fn finish_node(&mut self) { self.inner.finish_node() } pub fn error(&mut self, error: ParseError, text_pos: TextUnit) { let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos); self.errors.push(error) } }