1 //! This module defines Concrete Syntax Tree (CST), used by rust-analyzer. 2 //! 3 //! The CST includes comments and whitespace, provides a single node type, 4 //! `SyntaxNode`, and a basic traversal API (parent, children, siblings). 5 //! 6 //! The *real* implementation is in the (language-agnostic) `rowan` crate, this 7 //! module just wraps its API. 8 9 use rowan::{GreenNodeBuilder, Language}; 10 11 use crate::{Parse, SyntaxError, SyntaxKind, TextSize}; 12 13 pub(crate) use rowan::{GreenNode, GreenToken, NodeOrToken}; 14 15 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 16 pub enum RustLanguage {} 17 impl Language for RustLanguage { 18 type Kind = SyntaxKind; 19 kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind20 fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind { 21 SyntaxKind::from(raw.0) 22 } 23 kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind24 fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind { 25 rowan::SyntaxKind(kind.into()) 26 } 27 } 28 29 pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>; 30 pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>; 31 pub type SyntaxElement = rowan::SyntaxElement<RustLanguage>; 32 pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>; 33 pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>; 34 pub type PreorderWithTokens = rowan::api::PreorderWithTokens<RustLanguage>; 35 36 #[derive(Default)] 37 pub struct SyntaxTreeBuilder { 38 errors: Vec<SyntaxError>, 39 inner: GreenNodeBuilder<'static>, 40 } 41 42 impl SyntaxTreeBuilder { finish_raw(self) -> (GreenNode, Vec<SyntaxError>)43 pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) { 44 let green = self.inner.finish(); 45 (green, self.errors) 46 } 47 finish(self) -> Parse<SyntaxNode>48 pub fn finish(self) -> Parse<SyntaxNode> { 49 let (green, errors) = self.finish_raw(); 50 // Disable block validation, see https://github.com/rust-lang/rust-analyzer/pull/10357 51 #[allow(clippy::overly_complex_bool_expr)] 52 if cfg!(debug_assertions) && false { 53 let node = SyntaxNode::new_root(green.clone()); 54 crate::validation::validate_block_structure(&node); 55 } 56 Parse::new(green, errors) 57 } 58 token(&mut self, kind: SyntaxKind, text: &str)59 pub fn token(&mut self, kind: SyntaxKind, text: &str) { 60 let kind = RustLanguage::kind_to_raw(kind); 61 self.inner.token(kind, text); 62 } 63 start_node(&mut self, kind: SyntaxKind)64 pub fn start_node(&mut self, kind: SyntaxKind) { 65 let kind = RustLanguage::kind_to_raw(kind); 66 self.inner.start_node(kind); 67 } 68 finish_node(&mut self)69 pub fn finish_node(&mut self) { 70 self.inner.finish_node(); 71 } 72 error(&mut self, error: String, text_pos: TextSize)73 pub fn error(&mut self, error: String, text_pos: TextSize) { 74 self.errors.push(SyntaxError::new_at_offset(error, text_pos)); 75 } 76 } 77