1 //! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
3 //! The CST includes comments and whitespace, provides a single node type,
4 //! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
6 //! The *real* implementation is in the (language-agnostic) `rowan` crate, this
7 //! module just wraps its API.
9 use rowan
::{GreenNodeBuilder, Language}
;
11 use crate::{Parse, SyntaxError, SyntaxKind, TextSize}
;
13 pub(crate) use rowan
::{GreenNode, GreenToken, NodeOrToken}
;
15 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16 pub enum RustLanguage {}
17 impl Language
for RustLanguage
{
18 type Kind
= SyntaxKind
;
20 fn kind_from_raw(raw
: rowan
::SyntaxKind
) -> SyntaxKind
{
21 SyntaxKind
::from(raw
.0)
24 fn kind_to_raw(kind
: SyntaxKind
) -> rowan
::SyntaxKind
{
25 rowan
::SyntaxKind(kind
.into())
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
>;
37 pub struct SyntaxTreeBuilder
{
38 errors
: Vec
<SyntaxError
>,
39 inner
: GreenNodeBuilder
<'
static>,
42 impl SyntaxTreeBuilder
{
43 pub(crate) fn finish_raw(self) -> (GreenNode
, Vec
<SyntaxError
>) {
44 let green
= self.inner
.finish();
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
);
56 Parse
::new(green
, errors
)
59 pub fn token(&mut self, kind
: SyntaxKind
, text
: &str) {
60 let kind
= RustLanguage
::kind_to_raw(kind
);
61 self.inner
.token(kind
, text
);
64 pub fn start_node(&mut self, kind
: SyntaxKind
) {
65 let kind
= RustLanguage
::kind_to_raw(kind
);
66 self.inner
.start_node(kind
);
69 pub fn finish_node(&mut self) {
70 self.inner
.finish_node();
73 pub fn error(&mut self, error
: String
, text_pos
: TextSize
) {
74 self.errors
.push(SyntaxError
::new_at_offset(error
, text_pos
));