diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-02 15:14:56 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-02 15:14:56 +0100 |
commit | 7ffc114dab6d1e25ead195a5937cd4f9ca51ef2c (patch) | |
tree | e8bab3ea497a8e7207a24e481361bdd56ed81eaa /crates | |
parent | cd9c5f4ab205e092b87be6affe6d7e78d877dbf0 (diff) | |
parent | a261a1836ba02a1c091c5165795dc165ca399a87 (diff) |
Merge #85
85: start moving syntax tree to a separate crate r=matklad a=matklad
WIP
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_syntax/Cargo.toml | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/mod.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/reparsing.rs | 8 | ||||
-rw-r--r-- | crates/ra_syntax/src/utils.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/builder.rs | 32 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/green.rs | 90 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/mod.rs | 174 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/red.rs | 113 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/syntax.rs | 215 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/syntax_text.rs | 2 |
11 files changed, 137 insertions, 530 deletions
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index a0fd633e0..6345e4725 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -6,11 +6,10 @@ license = "MIT OR Apache-2.0" | |||
6 | 6 | ||
7 | [dependencies] | 7 | [dependencies] |
8 | unicode-xid = "0.1.0" | 8 | unicode-xid = "0.1.0" |
9 | text_unit = "0.1.4" | ||
10 | itertools = "0.7.8" | 9 | itertools = "0.7.8" |
11 | drop_bomb = "0.1.4" | 10 | drop_bomb = "0.1.4" |
12 | parking_lot = "0.6.0" | 11 | parking_lot = "0.6.0" |
13 | smol_str = "0.1.6" | 12 | rowan = "0.1.0" |
14 | 13 | ||
15 | [dev-dependencies] | 14 | [dev-dependencies] |
16 | test_utils = { path = "../test_utils" } | 15 | test_utils = { path = "../test_utils" } |
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs index a6da82957..c1570b868 100644 --- a/crates/ra_syntax/src/ast/mod.rs +++ b/crates/ra_syntax/src/ast/mod.rs | |||
@@ -3,10 +3,9 @@ mod generated; | |||
3 | use std::marker::PhantomData; | 3 | use std::marker::PhantomData; |
4 | 4 | ||
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use smol_str::SmolStr; | ||
7 | 6 | ||
8 | use { | 7 | use { |
9 | SyntaxNodeRef, SyntaxKind::*, | 8 | SmolStr, SyntaxNodeRef, SyntaxKind::*, |
10 | yellow::{RefRoot, SyntaxNodeChildren}, | 9 | yellow::{RefRoot, SyntaxNodeChildren}, |
11 | }; | 10 | }; |
12 | pub use self::generated::*; | 11 | pub use self::generated::*; |
@@ -76,7 +75,7 @@ impl<'a> Attr<'a> { | |||
76 | let tt = self.value()?; | 75 | let tt = self.value()?; |
77 | let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; | 76 | let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; |
78 | if attr.kind() == IDENT { | 77 | if attr.kind() == IDENT { |
79 | Some(attr.leaf_text().unwrap()) | 78 | Some(attr.leaf_text().unwrap().clone()) |
80 | } else { | 79 | } else { |
81 | None | 80 | None |
82 | } | 81 | } |
@@ -87,7 +86,7 @@ impl<'a> Attr<'a> { | |||
87 | let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; | 86 | let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; |
88 | let args = TokenTree::cast(args)?; | 87 | let args = TokenTree::cast(args)?; |
89 | if attr.kind() == IDENT { | 88 | if attr.kind() == IDENT { |
90 | Some((attr.leaf_text().unwrap(), args)) | 89 | Some((attr.leaf_text().unwrap().clone(), args)) |
91 | } else { | 90 | } else { |
92 | None | 91 | None |
93 | } | 92 | } |
@@ -96,7 +95,7 @@ impl<'a> Attr<'a> { | |||
96 | 95 | ||
97 | impl<'a> Lifetime<'a> { | 96 | impl<'a> Lifetime<'a> { |
98 | pub fn text(&self) -> SmolStr { | 97 | pub fn text(&self) -> SmolStr { |
99 | self.syntax().leaf_text().unwrap() | 98 | self.syntax().leaf_text().unwrap().clone() |
100 | } | 99 | } |
101 | } | 100 | } |
102 | 101 | ||
@@ -104,7 +103,7 @@ impl<'a> Name<'a> { | |||
104 | pub fn text(&self) -> SmolStr { | 103 | pub fn text(&self) -> SmolStr { |
105 | let ident = self.syntax().first_child() | 104 | let ident = self.syntax().first_child() |
106 | .unwrap(); | 105 | .unwrap(); |
107 | ident.leaf_text().unwrap() | 106 | ident.leaf_text().unwrap().clone() |
108 | } | 107 | } |
109 | } | 108 | } |
110 | 109 | ||
@@ -112,7 +111,7 @@ impl<'a> NameRef<'a> { | |||
112 | pub fn text(&self) -> SmolStr { | 111 | pub fn text(&self) -> SmolStr { |
113 | let ident = self.syntax().first_child() | 112 | let ident = self.syntax().first_child() |
114 | .unwrap(); | 113 | .unwrap(); |
115 | ident.leaf_text().unwrap() | 114 | ident.leaf_text().unwrap().clone() |
116 | } | 115 | } |
117 | } | 116 | } |
118 | 117 | ||
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index eb271762e..c7eda4563 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -24,8 +24,7 @@ extern crate itertools; | |||
24 | extern crate unicode_xid; | 24 | extern crate unicode_xid; |
25 | extern crate drop_bomb; | 25 | extern crate drop_bomb; |
26 | extern crate parking_lot; | 26 | extern crate parking_lot; |
27 | extern crate smol_str; | 27 | extern crate rowan; |
28 | extern crate text_unit; | ||
29 | 28 | ||
30 | #[cfg(test)] | 29 | #[cfg(test)] |
31 | #[macro_use] | 30 | #[macro_use] |
@@ -48,8 +47,7 @@ pub mod utils; | |||
48 | pub mod text_utils; | 47 | pub mod text_utils; |
49 | 48 | ||
50 | pub use { | 49 | pub use { |
51 | text_unit::{TextRange, TextUnit}, | 50 | rowan::{SmolStr, TextRange, TextUnit}, |
52 | smol_str::SmolStr, | ||
53 | ast::AstNode, | 51 | ast::AstNode, |
54 | lexer::{tokenize, Token}, | 52 | lexer::{tokenize, Token}, |
55 | syntax_kinds::SyntaxKind, | 53 | syntax_kinds::SyntaxKind, |
@@ -58,7 +56,7 @@ pub use { | |||
58 | }; | 56 | }; |
59 | 57 | ||
60 | use { | 58 | use { |
61 | yellow::{GreenNode, SyntaxRoot}, | 59 | yellow::{GreenNode}, |
62 | }; | 60 | }; |
63 | 61 | ||
64 | #[derive(Clone, Debug, Hash)] | 62 | #[derive(Clone, Debug, Hash)] |
@@ -68,8 +66,7 @@ pub struct File { | |||
68 | 66 | ||
69 | impl File { | 67 | impl File { |
70 | fn new(green: GreenNode, errors: Vec<SyntaxError>) -> File { | 68 | fn new(green: GreenNode, errors: Vec<SyntaxError>) -> File { |
71 | let root = SyntaxRoot::new(green, errors); | 69 | let root = SyntaxNode::new(green, errors); |
72 | let root = SyntaxNode::new_owned(root); | ||
73 | if cfg!(debug_assertions) { | 70 | if cfg!(debug_assertions) { |
74 | utils::validate_block_structure(root.borrowed()); | 71 | utils::validate_block_structure(root.borrowed()); |
75 | } | 72 | } |
@@ -100,6 +97,6 @@ impl File { | |||
100 | self.root.borrowed() | 97 | self.root.borrowed() |
101 | } | 98 | } |
102 | pub fn errors(&self) -> Vec<SyntaxError> { | 99 | pub fn errors(&self) -> Vec<SyntaxError> { |
103 | self.syntax().root.syntax_root().errors.clone() | 100 | self.root.root_data().clone() |
104 | } | 101 | } |
105 | } | 102 | } |
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index da44913c5..e3c200d1e 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | use algo; | 1 | use algo; |
2 | use grammar; | 2 | use grammar; |
3 | use lexer::{tokenize, Token}; | 3 | use lexer::{tokenize, Token}; |
4 | use text_unit::{TextRange, TextUnit}; | 4 | use yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError}; |
5 | use yellow::{self, SyntaxNodeRef, GreenNode, SyntaxError}; | ||
6 | use parser_impl; | 5 | use parser_impl; |
7 | use parser_api::Parser; | 6 | use parser_api::Parser; |
8 | use { | 7 | use { |
8 | TextUnit, TextRange, | ||
9 | SyntaxKind::*, | 9 | SyntaxKind::*, |
10 | }; | 10 | }; |
11 | use text_utils::replace_range; | 11 | use text_utils::replace_range; |
@@ -65,7 +65,7 @@ fn reparse_leaf<'node>( | |||
65 | return None; | 65 | return None; |
66 | } | 66 | } |
67 | 67 | ||
68 | let green = GreenNode::new_leaf(node.kind(), &text); | 68 | let green = GreenNode::new_leaf(node.kind(), text.into()); |
69 | let new_errors = vec![]; | 69 | let new_errors = vec![]; |
70 | Some((node, green, new_errors)) | 70 | Some((node, green, new_errors)) |
71 | } | 71 | } |
@@ -340,4 +340,4 @@ enum Foo { | |||
340 | } | 340 | } |
341 | ", "Clone"); | 341 | ", "Clone"); |
342 | } | 342 | } |
343 | } \ No newline at end of file | 343 | } |
diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index 671dd7afa..8bc5f0e24 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | use { | 2 | use { |
3 | algo::walk::{preorder, walk, WalkEvent}, | 3 | algo::walk::{preorder, walk, WalkEvent}, |
4 | SyntaxKind, File, SyntaxNodeRef, TreeRoot, | 4 | SyntaxKind, File, SyntaxNodeRef |
5 | }; | 5 | }; |
6 | 6 | ||
7 | /// Parse a file and create a string representation of the resulting parse tree. | 7 | /// Parse a file and create a string representation of the resulting parse tree. |
8 | pub fn dump_tree(syntax: SyntaxNodeRef) -> String { | 8 | pub fn dump_tree(syntax: SyntaxNodeRef) -> String { |
9 | let mut errors: Vec<_> = syntax.root.syntax_root().errors.iter().cloned().collect(); | 9 | let mut errors: Vec<_> = syntax.root_data().iter().cloned().collect(); |
10 | errors.sort_by_key(|e| e.offset); | 10 | errors.sort_by_key(|e| e.offset); |
11 | let mut err_pos = 0; | 11 | let mut err_pos = 0; |
12 | let mut level = 0; | 12 | let mut level = 0; |
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs index e4ab37899..35dbaec05 100644 --- a/crates/ra_syntax/src/yellow/builder.rs +++ b/crates/ra_syntax/src/yellow/builder.rs | |||
@@ -1,15 +1,15 @@ | |||
1 | use rowan::GreenNodeBuilder; | ||
1 | use { | 2 | use { |
2 | parser_impl::Sink, | 3 | parser_impl::Sink, |
3 | yellow::{GreenNode, SyntaxError}, | 4 | yellow::{GreenNode, SyntaxError, RaTypes}, |
4 | SyntaxKind, TextRange, TextUnit, | 5 | SyntaxKind, TextRange, TextUnit, |
5 | }; | 6 | }; |
6 | 7 | ||
7 | pub(crate) struct GreenBuilder<'a> { | 8 | pub(crate) struct GreenBuilder<'a> { |
8 | text: &'a str, | 9 | text: &'a str, |
9 | parents: Vec<(SyntaxKind, usize)>, | ||
10 | children: Vec<GreenNode>, | ||
11 | pos: TextUnit, | 10 | pos: TextUnit, |
12 | errors: Vec<SyntaxError>, | 11 | errors: Vec<SyntaxError>, |
12 | inner: GreenNodeBuilder<RaTypes>, | ||
13 | } | 13 | } |
14 | 14 | ||
15 | impl<'a> Sink<'a> for GreenBuilder<'a> { | 15 | impl<'a> Sink<'a> for GreenBuilder<'a> { |
@@ -18,35 +18,25 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
18 | fn new(text: &'a str) -> Self { | 18 | fn new(text: &'a str) -> Self { |
19 | GreenBuilder { | 19 | GreenBuilder { |
20 | text, | 20 | text, |
21 | parents: Vec::new(), | ||
22 | children: Vec::new(), | ||
23 | pos: 0.into(), | 21 | pos: 0.into(), |
24 | errors: Vec::new(), | 22 | errors: Vec::new(), |
23 | inner: GreenNodeBuilder::new(), | ||
25 | } | 24 | } |
26 | } | 25 | } |
27 | 26 | ||
28 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { | 27 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) { |
29 | let range = TextRange::offset_len(self.pos, len); | 28 | let range = TextRange::offset_len(self.pos, len); |
30 | self.pos += len; | 29 | self.pos += len; |
31 | let text = &self.text[range]; | 30 | let text = self.text[range].into(); |
32 | self.children.push( | 31 | self.inner.leaf(kind, text); |
33 | GreenNode::new_leaf(kind, text) | ||
34 | ); | ||
35 | } | 32 | } |
36 | 33 | ||
37 | fn start_internal(&mut self, kind: SyntaxKind) { | 34 | fn start_internal(&mut self, kind: SyntaxKind) { |
38 | let len = self.children.len(); | 35 | self.inner.start_internal(kind) |
39 | self.parents.push((kind, len)); | ||
40 | } | 36 | } |
41 | 37 | ||
42 | fn finish_internal(&mut self) { | 38 | fn finish_internal(&mut self) { |
43 | let (kind, first_child) = self.parents.pop().unwrap(); | 39 | self.inner.finish_internal(); |
44 | let children: Vec<_> = self.children | ||
45 | .drain(first_child..) | ||
46 | .collect(); | ||
47 | self.children.push( | ||
48 | GreenNode::new_branch(kind, children.into_boxed_slice()) | ||
49 | ); | ||
50 | } | 40 | } |
51 | 41 | ||
52 | fn error(&mut self, message: String) { | 42 | fn error(&mut self, message: String) { |
@@ -56,9 +46,7 @@ impl<'a> Sink<'a> for GreenBuilder<'a> { | |||
56 | }) | 46 | }) |
57 | } | 47 | } |
58 | 48 | ||
59 | fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) { | 49 | fn finish(self) -> (GreenNode, Vec<SyntaxError>) { |
60 | assert_eq!(self.children.len(), 1); | 50 | (self.inner.finish(), self.errors) |
61 | let root = self.children.pop().unwrap(); | ||
62 | (root, self.errors) | ||
63 | } | 51 | } |
64 | } | 52 | } |
diff --git a/crates/ra_syntax/src/yellow/green.rs b/crates/ra_syntax/src/yellow/green.rs deleted file mode 100644 index 8fb691643..000000000 --- a/crates/ra_syntax/src/yellow/green.rs +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use smol_str::SmolStr; | ||
4 | |||
5 | use {SyntaxKind, TextUnit}; | ||
6 | |||
7 | #[derive(Clone, Debug)] | ||
8 | pub(crate) enum GreenNode { | ||
9 | Leaf { | ||
10 | kind: SyntaxKind, | ||
11 | text: SmolStr, | ||
12 | }, | ||
13 | Branch(Arc<GreenBranch>), | ||
14 | } | ||
15 | |||
16 | impl GreenNode { | ||
17 | pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode { | ||
18 | GreenNode::Leaf { kind, text: SmolStr::new(text) } | ||
19 | } | ||
20 | |||
21 | pub(crate) fn new_branch(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenNode { | ||
22 | GreenNode::Branch(Arc::new(GreenBranch::new(kind, children))) | ||
23 | } | ||
24 | |||
25 | pub fn kind(&self) -> SyntaxKind { | ||
26 | match self { | ||
27 | GreenNode::Leaf { kind, .. } => *kind, | ||
28 | GreenNode::Branch(b) => b.kind(), | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub fn text_len(&self) -> TextUnit { | ||
33 | match self { | ||
34 | GreenNode::Leaf { text, .. } => TextUnit::from(text.len() as u32), | ||
35 | GreenNode::Branch(b) => b.text_len(), | ||
36 | } | ||
37 | } | ||
38 | |||
39 | pub fn children(&self) -> &[GreenNode] { | ||
40 | match self { | ||
41 | GreenNode::Leaf { .. } => &[], | ||
42 | GreenNode::Branch(b) => b.children(), | ||
43 | } | ||
44 | } | ||
45 | |||
46 | pub fn leaf_text_ref(&self) -> Option<&SmolStr> { | ||
47 | match self { | ||
48 | GreenNode::Leaf { text, .. } => Some(text), | ||
49 | GreenNode::Branch(_) => None, | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | #[derive(Clone, Debug)] | ||
55 | pub(crate) struct GreenBranch { | ||
56 | text_len: TextUnit, | ||
57 | kind: SyntaxKind, | ||
58 | children: Box<[GreenNode]>, | ||
59 | } | ||
60 | |||
61 | impl GreenBranch { | ||
62 | fn new(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenBranch { | ||
63 | let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>(); | ||
64 | GreenBranch { | ||
65 | text_len, | ||
66 | kind, | ||
67 | children, | ||
68 | } | ||
69 | } | ||
70 | |||
71 | pub fn kind(&self) -> SyntaxKind { | ||
72 | self.kind | ||
73 | } | ||
74 | |||
75 | pub fn text_len(&self) -> TextUnit { | ||
76 | self.text_len | ||
77 | } | ||
78 | |||
79 | pub fn children(&self) -> &[GreenNode] { | ||
80 | &*self.children | ||
81 | } | ||
82 | } | ||
83 | |||
84 | #[test] | ||
85 | fn test_sizes() { | ||
86 | use std::mem::size_of; | ||
87 | println!("GreenBranch = {}", size_of::<GreenBranch>()); | ||
88 | println!("GreenNode = {}", size_of::<GreenNode>()); | ||
89 | println!("SmolStr = {}", size_of::<SmolStr>()); | ||
90 | } | ||
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index 0596e702f..c621b1d6a 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs | |||
@@ -1,100 +1,142 @@ | |||
1 | mod builder; | 1 | mod builder; |
2 | mod green; | ||
3 | mod red; | ||
4 | mod syntax; | ||
5 | mod syntax_text; | 2 | mod syntax_text; |
6 | 3 | ||
7 | use std::{ | 4 | use std::{ |
8 | sync::Arc, | 5 | fmt, |
9 | ptr, | 6 | hash::{Hash, Hasher}, |
10 | }; | ||
11 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren}; | ||
12 | pub(crate) use self::{ | ||
13 | builder::GreenBuilder, | ||
14 | green::GreenNode, | ||
15 | red::RedNode, | ||
16 | syntax_text::SyntaxText, | ||
17 | }; | 7 | }; |
8 | use rowan::Types; | ||
9 | use {SyntaxKind, TextUnit, TextRange, SmolStr}; | ||
10 | use self::syntax_text::SyntaxText; | ||
18 | 11 | ||
19 | #[derive(Debug)] | 12 | pub use rowan::{TreeRoot}; |
20 | pub struct SyntaxRoot { | 13 | pub(crate) use self::builder::GreenBuilder; |
21 | red: RedNode, | 14 | |
22 | pub(crate) errors: Vec<SyntaxError>, | 15 | #[derive(Debug, Clone, Copy)] |
16 | pub enum RaTypes {} | ||
17 | impl Types for RaTypes { | ||
18 | type Kind = SyntaxKind; | ||
19 | type RootData = Vec<SyntaxError>; | ||
23 | } | 20 | } |
24 | 21 | ||
25 | pub trait TreeRoot: Clone + Send + Sync { | 22 | pub type OwnedRoot = ::rowan::OwnedRoot<RaTypes>; |
26 | fn borrowed(&self) -> RefRoot; | 23 | pub type RefRoot<'a> = ::rowan::RefRoot<'a, RaTypes>; |
27 | fn owned(&self) -> OwnedRoot; | 24 | |
25 | pub type GreenNode = ::rowan::GreenNode<RaTypes>; | ||
28 | 26 | ||
29 | #[doc(hidden)] | 27 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
30 | fn syntax_root(&self) -> &SyntaxRoot; | 28 | pub struct SyntaxError { |
29 | pub msg: String, | ||
30 | pub offset: TextUnit, | ||
31 | } | 31 | } |
32 | #[derive(Clone, Debug)] | ||
33 | pub struct OwnedRoot(Arc<SyntaxRoot>); | ||
34 | #[derive(Clone, Copy, Debug)] | ||
35 | pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection | ||
36 | 32 | ||
37 | impl<'a> RefRoot<'a> { | 33 | #[derive(Clone, Copy)] |
38 | fn syntax_root(&self) -> &'a SyntaxRoot { | 34 | pub struct SyntaxNode<R: TreeRoot<RaTypes> = OwnedRoot>( |
39 | self.0.syntax_root() | 35 | ::rowan::SyntaxNode<RaTypes, R>, |
36 | ); | ||
37 | pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>; | ||
38 | |||
39 | impl<R1, R2> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> | ||
40 | where | ||
41 | R1: TreeRoot<RaTypes>, | ||
42 | R2: TreeRoot<RaTypes>, | ||
43 | { | ||
44 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { | ||
45 | self.0 == other.0 | ||
40 | } | 46 | } |
41 | } | 47 | } |
42 | 48 | ||
43 | impl TreeRoot for OwnedRoot { | 49 | impl<R: TreeRoot<RaTypes>> Eq for SyntaxNode<R> {} |
44 | fn borrowed(&self) -> RefRoot { | 50 | impl<R: TreeRoot<RaTypes>> Hash for SyntaxNode<R> { |
45 | RefRoot(&self) | 51 | fn hash<H: Hasher>(&self, state: &mut H) { |
46 | } | 52 | self.0.hash(state) |
47 | fn owned(&self) -> OwnedRoot { | ||
48 | self.clone() | ||
49 | } | 53 | } |
54 | } | ||
50 | 55 | ||
51 | fn syntax_root(&self) -> &SyntaxRoot { | 56 | impl SyntaxNode<OwnedRoot> { |
52 | &*self.0 | 57 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxNode { |
58 | SyntaxNode(::rowan::SyntaxNode::new(green, errors)) | ||
59 | } | ||
60 | } | ||
61 | impl<'a> SyntaxNode<RefRoot<'a>> { | ||
62 | pub fn leaf_text(self) -> Option<&'a SmolStr> { | ||
63 | self.0.leaf_text() | ||
53 | } | 64 | } |
54 | } | 65 | } |
55 | 66 | ||
56 | impl<'a> TreeRoot for RefRoot<'a> { | 67 | impl<R: TreeRoot<RaTypes>> SyntaxNode<R> { |
57 | fn borrowed(&self) -> RefRoot { | 68 | pub(crate) fn root_data(&self) -> &Vec<SyntaxError> { |
58 | *self | 69 | self.0.root_data() |
70 | } | ||
71 | pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { | ||
72 | self.0.replace_with(replacement) | ||
73 | } | ||
74 | pub fn borrowed<'a>(&'a self) -> SyntaxNode<RefRoot<'a>> { | ||
75 | SyntaxNode(self.0.borrowed()) | ||
76 | } | ||
77 | pub fn owned(&self) -> SyntaxNode<OwnedRoot> { | ||
78 | SyntaxNode(self.0.owned()) | ||
79 | } | ||
80 | pub fn kind(&self) -> SyntaxKind { | ||
81 | self.0.kind() | ||
59 | } | 82 | } |
60 | fn owned(&self) -> OwnedRoot { | 83 | pub fn range(&self) -> TextRange { |
61 | self.0.clone() | 84 | self.0.range() |
62 | } | 85 | } |
63 | fn syntax_root(&self) -> &SyntaxRoot { | 86 | pub fn text(&self) -> SyntaxText { |
64 | self.0.syntax_root() | 87 | SyntaxText::new(self.borrowed()) |
88 | } | ||
89 | pub fn is_leaf(&self) -> bool { | ||
90 | self.0.is_leaf() | ||
91 | } | ||
92 | pub fn parent(&self) -> Option<SyntaxNode<R>> { | ||
93 | self.0.parent().map(SyntaxNode) | ||
94 | } | ||
95 | pub fn first_child(&self) -> Option<SyntaxNode<R>> { | ||
96 | self.0.first_child().map(SyntaxNode) | ||
97 | } | ||
98 | pub fn last_child(&self) -> Option<SyntaxNode<R>> { | ||
99 | self.0.last_child().map(SyntaxNode) | ||
100 | } | ||
101 | pub fn next_sibling(&self) -> Option<SyntaxNode<R>> { | ||
102 | self.0.next_sibling().map(SyntaxNode) | ||
103 | } | ||
104 | pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> { | ||
105 | self.0.prev_sibling().map(SyntaxNode) | ||
106 | } | ||
107 | pub fn children(&self) -> SyntaxNodeChildren<R> { | ||
108 | SyntaxNodeChildren(self.0.children()) | ||
65 | } | 109 | } |
66 | } | 110 | } |
67 | 111 | ||
68 | impl SyntaxRoot { | 112 | impl<R: TreeRoot<RaTypes>> fmt::Debug for SyntaxNode<R> { |
69 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | 113 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
70 | SyntaxRoot { | 114 | write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; |
71 | red: RedNode::new_root(green), | 115 | if has_short_text(self.kind()) { |
72 | errors, | 116 | write!(fmt, " \"{}\"", self.text())?; |
73 | } | 117 | } |
118 | Ok(()) | ||
74 | } | 119 | } |
75 | } | 120 | } |
76 | 121 | ||
77 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 122 | #[derive(Debug)] |
78 | pub(crate) struct RedPtr(ptr::NonNull<RedNode>); | 123 | pub struct SyntaxNodeChildren<R: TreeRoot<RaTypes>>( |
79 | 124 | ::rowan::SyntaxNodeChildren<RaTypes, R> | |
80 | unsafe impl Send for RedPtr {} | 125 | ); |
81 | |||
82 | unsafe impl Sync for RedPtr {} | ||
83 | 126 | ||
84 | impl RedPtr { | 127 | impl<R: TreeRoot<RaTypes>> Iterator for SyntaxNodeChildren<R> { |
85 | fn new(red: &RedNode) -> RedPtr { | 128 | type Item = SyntaxNode<R>; |
86 | RedPtr(red.into()) | ||
87 | } | ||
88 | 129 | ||
89 | unsafe fn get<'a>(self, _root: &'a SyntaxRoot) -> &'a RedNode { | 130 | fn next(&mut self) -> Option<SyntaxNode<R>> { |
90 | &*self.0.as_ptr() | 131 | self.0.next().map(SyntaxNode) |
91 | } | 132 | } |
92 | } | 133 | } |
93 | 134 | ||
94 | #[test] | 135 | |
95 | fn assert_send_sync() { | 136 | fn has_short_text(kind: SyntaxKind) -> bool { |
96 | fn f<T: Send + Sync>() {} | 137 | use SyntaxKind::*; |
97 | f::<GreenNode>(); | 138 | match kind { |
98 | f::<RedNode>(); | 139 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, |
99 | f::<SyntaxNode>(); | 140 | _ => false, |
141 | } | ||
100 | } | 142 | } |
diff --git a/crates/ra_syntax/src/yellow/red.rs b/crates/ra_syntax/src/yellow/red.rs deleted file mode 100644 index 84cfe4fba..000000000 --- a/crates/ra_syntax/src/yellow/red.rs +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | use parking_lot::RwLock; | ||
2 | use {yellow::{GreenNode, RedPtr}, TextUnit}; | ||
3 | |||
4 | #[derive(Debug)] | ||
5 | pub(crate) struct RedNode { | ||
6 | green: GreenNode, | ||
7 | parent: Option<ParentData>, | ||
8 | children: RwLock<Box<[RedChild]>>, | ||
9 | } | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | enum RedChild { | ||
13 | Zigot(TextUnit), | ||
14 | Child(RedNode) | ||
15 | } | ||
16 | |||
17 | impl RedChild { | ||
18 | fn set(&mut self, node: RedNode) -> &RedNode { | ||
19 | match self { | ||
20 | RedChild::Child(node) => return node, | ||
21 | RedChild::Zigot(_) => { | ||
22 | *self = RedChild::Child(node); | ||
23 | match self { | ||
24 | RedChild::Child(node) => return node, | ||
25 | RedChild::Zigot(_) => unreachable!() | ||
26 | } | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | |||
32 | #[derive(Debug)] | ||
33 | struct ParentData { | ||
34 | parent: RedPtr, | ||
35 | start_offset: TextUnit, | ||
36 | index_in_parent: usize, | ||
37 | } | ||
38 | |||
39 | impl RedNode { | ||
40 | pub fn new_root(green: GreenNode) -> RedNode { | ||
41 | RedNode::new(green, None) | ||
42 | } | ||
43 | |||
44 | fn new_child( | ||
45 | green: GreenNode, | ||
46 | parent: RedPtr, | ||
47 | start_offset: TextUnit, | ||
48 | index_in_parent: usize, | ||
49 | ) -> RedNode { | ||
50 | let parent_data = ParentData { | ||
51 | parent, | ||
52 | start_offset, | ||
53 | index_in_parent, | ||
54 | }; | ||
55 | RedNode::new(green, Some(parent_data)) | ||
56 | } | ||
57 | |||
58 | fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode { | ||
59 | let mut start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into()); | ||
60 | let children = green.children() | ||
61 | .iter() | ||
62 | .map(|child| { | ||
63 | let off = start_offset; | ||
64 | start_offset += child.text_len(); | ||
65 | RedChild::Zigot(off) | ||
66 | }) | ||
67 | .collect::<Vec<_>>() | ||
68 | .into_boxed_slice(); | ||
69 | RedNode { | ||
70 | green, | ||
71 | parent, | ||
72 | children: RwLock::new(children), | ||
73 | } | ||
74 | } | ||
75 | |||
76 | pub(crate) fn green(&self) -> &GreenNode { | ||
77 | &self.green | ||
78 | } | ||
79 | |||
80 | pub(crate) fn start_offset(&self) -> TextUnit { | ||
81 | match &self.parent { | ||
82 | None => 0.into(), | ||
83 | Some(p) => p.start_offset, | ||
84 | } | ||
85 | } | ||
86 | |||
87 | pub(crate) fn n_children(&self) -> usize { | ||
88 | self.green.children().len() | ||
89 | } | ||
90 | |||
91 | pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> { | ||
92 | if idx >= self.n_children() { | ||
93 | return None; | ||
94 | } | ||
95 | let start_offset = match &self.children.read()[idx] { | ||
96 | RedChild::Child(child) => return Some(RedPtr::new(child)), | ||
97 | RedChild::Zigot(start_offset) => *start_offset, | ||
98 | }; | ||
99 | let green_children = self.green.children(); | ||
100 | let child = | ||
101 | RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx); | ||
102 | let mut children = self.children.write(); | ||
103 | let child = children[idx].set(child); | ||
104 | Some(RedPtr::new(child)) | ||
105 | } | ||
106 | |||
107 | pub(crate) fn parent(&self) -> Option<RedPtr> { | ||
108 | Some(self.parent.as_ref()?.parent) | ||
109 | } | ||
110 | pub(crate) fn index_in_parent(&self) -> Option<usize> { | ||
111 | Some(self.parent.as_ref()?.index_in_parent) | ||
112 | } | ||
113 | } | ||
diff --git a/crates/ra_syntax/src/yellow/syntax.rs b/crates/ra_syntax/src/yellow/syntax.rs deleted file mode 100644 index 1d99cab4a..000000000 --- a/crates/ra_syntax/src/yellow/syntax.rs +++ /dev/null | |||
@@ -1,215 +0,0 @@ | |||
1 | use std::{ | ||
2 | fmt, sync::Arc, | ||
3 | hash::{Hasher, Hash}, | ||
4 | ops::Range, | ||
5 | }; | ||
6 | |||
7 | use smol_str::SmolStr; | ||
8 | |||
9 | use { | ||
10 | yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText}, | ||
11 | SyntaxKind::{self, *}, | ||
12 | TextRange, TextUnit, | ||
13 | }; | ||
14 | |||
15 | |||
16 | #[derive(Clone, Copy)] | ||
17 | pub struct SyntaxNode<R: TreeRoot = OwnedRoot> { | ||
18 | pub(crate) root: R, | ||
19 | // Guaranteed to not dangle, because `root` holds a | ||
20 | // strong reference to red's ancestor | ||
21 | red: RedPtr, | ||
22 | } | ||
23 | |||
24 | unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {} | ||
25 | unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {} | ||
26 | |||
27 | impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> { | ||
28 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { | ||
29 | self.red == other.red | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl<R: TreeRoot> Eq for SyntaxNode<R> {} | ||
34 | impl<R: TreeRoot> Hash for SyntaxNode<R> { | ||
35 | fn hash<H: Hasher>(&self, state: &mut H) { | ||
36 | self.red.hash(state) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>; | ||
41 | |||
42 | #[test] | ||
43 | fn syntax_node_ref_is_copy() { | ||
44 | fn assert_copy<T: Copy>(){} | ||
45 | assert_copy::<SyntaxNodeRef>() | ||
46 | } | ||
47 | |||
48 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
49 | pub struct SyntaxError { | ||
50 | pub msg: String, | ||
51 | pub offset: TextUnit, | ||
52 | } | ||
53 | |||
54 | impl SyntaxNode<OwnedRoot> { | ||
55 | pub(crate) fn new_owned(root: SyntaxRoot) -> Self { | ||
56 | let root = OwnedRoot(Arc::new(root)); | ||
57 | let red = RedPtr::new(&root.syntax_root().red); | ||
58 | SyntaxNode { root, red } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | impl<'a> SyntaxNode<RefRoot<'a>> { | ||
63 | pub(crate) fn leaf_text_ref(self) -> Option<&'a SmolStr> { | ||
64 | let red = unsafe { self.red.get(self.root.syntax_root()) }; | ||
65 | red.green().leaf_text_ref() | ||
66 | } | ||
67 | } | ||
68 | |||
69 | impl<R: TreeRoot> SyntaxNode<R> { | ||
70 | pub fn borrowed<'a>(&'a self) -> SyntaxNodeRef<'a> { | ||
71 | SyntaxNode { | ||
72 | root: self.root.borrowed(), | ||
73 | red: self.red, | ||
74 | } | ||
75 | } | ||
76 | |||
77 | pub fn owned(&self) -> SyntaxNode { | ||
78 | SyntaxNode { | ||
79 | root: self.root.owned(), | ||
80 | red: self.red, | ||
81 | } | ||
82 | } | ||
83 | |||
84 | pub fn kind(&self) -> SyntaxKind { | ||
85 | self.red().green().kind() | ||
86 | } | ||
87 | |||
88 | pub fn range(&self) -> TextRange { | ||
89 | let red = self.red(); | ||
90 | TextRange::offset_len(red.start_offset(), red.green().text_len()) | ||
91 | } | ||
92 | |||
93 | pub fn text(&self) -> SyntaxText { | ||
94 | SyntaxText::new(self.borrowed()) | ||
95 | } | ||
96 | |||
97 | pub fn children(&self) -> SyntaxNodeChildren<R> { | ||
98 | SyntaxNodeChildren { | ||
99 | parent: self.clone(), | ||
100 | iter: (0..self.red().n_children()) | ||
101 | } | ||
102 | } | ||
103 | |||
104 | pub fn parent(&self) -> Option<SyntaxNode<R>> { | ||
105 | let parent = self.red().parent()?; | ||
106 | Some(SyntaxNode { | ||
107 | root: self.root.clone(), | ||
108 | red: parent, | ||
109 | }) | ||
110 | } | ||
111 | |||
112 | pub fn first_child(&self) -> Option<SyntaxNode<R>> { | ||
113 | let red = self.red().get_child(0)?; | ||
114 | Some(SyntaxNode { root: self.root.clone(), red }) | ||
115 | } | ||
116 | |||
117 | pub fn last_child(&self) -> Option<SyntaxNode<R>> { | ||
118 | let n = self.red().n_children(); | ||
119 | let n = n.checked_sub(1)?; | ||
120 | let red = self.red().get_child(n)?; | ||
121 | Some(SyntaxNode { root: self.root.clone(), red }) | ||
122 | } | ||
123 | |||
124 | pub fn next_sibling(&self) -> Option<SyntaxNode<R>> { | ||
125 | let red = self.red(); | ||
126 | let parent = self.parent()?; | ||
127 | let next_sibling_idx = red.index_in_parent()? + 1; | ||
128 | let sibling_red = parent.red().get_child(next_sibling_idx)?; | ||
129 | Some(SyntaxNode { | ||
130 | root: self.root.clone(), | ||
131 | red: sibling_red, | ||
132 | }) | ||
133 | } | ||
134 | |||
135 | pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> { | ||
136 | let red = self.red(); | ||
137 | let parent = self.parent()?; | ||
138 | let prev_sibling_idx = red.index_in_parent()?.checked_sub(1)?; | ||
139 | let sibling_red = parent.red().get_child(prev_sibling_idx)?; | ||
140 | Some(SyntaxNode { | ||
141 | root: self.root.clone(), | ||
142 | red: sibling_red, | ||
143 | }) | ||
144 | } | ||
145 | |||
146 | pub fn is_leaf(&self) -> bool { | ||
147 | self.first_child().is_none() | ||
148 | } | ||
149 | |||
150 | pub fn leaf_text(&self) -> Option<SmolStr> { | ||
151 | self.borrowed().leaf_text_ref().map(|it| it.clone()) | ||
152 | } | ||
153 | |||
154 | pub(crate) fn replace_with(&self, green: GreenNode) -> GreenNode { | ||
155 | assert_eq!(self.kind(), green.kind()); | ||
156 | match self.parent() { | ||
157 | None => green, | ||
158 | Some(parent) => { | ||
159 | let children: Vec<_> = parent.children().map(|child| { | ||
160 | if child == *self { | ||
161 | green.clone() | ||
162 | } else { | ||
163 | child.red().green().clone() | ||
164 | } | ||
165 | }).collect(); | ||
166 | let new_parent = GreenNode::new_branch( | ||
167 | parent.kind(), | ||
168 | children.into_boxed_slice(), | ||
169 | ); | ||
170 | parent.replace_with(new_parent) | ||
171 | }, | ||
172 | } | ||
173 | } | ||
174 | |||
175 | fn red(&self) -> &RedNode { | ||
176 | unsafe { self.red.get(self.root.syntax_root()) } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> { | ||
181 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
182 | write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; | ||
183 | if has_short_text(self.kind()) { | ||
184 | write!(fmt, " \"{}\"", self.text())?; | ||
185 | } | ||
186 | Ok(()) | ||
187 | } | ||
188 | } | ||
189 | |||
190 | #[derive(Debug)] | ||
191 | pub struct SyntaxNodeChildren<R: TreeRoot> { | ||
192 | parent: SyntaxNode<R>, | ||
193 | iter: Range<usize>, | ||
194 | } | ||
195 | |||
196 | impl<R: TreeRoot> Iterator for SyntaxNodeChildren<R> { | ||
197 | type Item = SyntaxNode<R>; | ||
198 | |||
199 | fn next(&mut self) -> Option<SyntaxNode<R>> { | ||
200 | self.iter.next().map(|i| { | ||
201 | let red = self.parent.red(); | ||
202 | SyntaxNode { | ||
203 | root: self.parent.root.clone(), | ||
204 | red: red.get_child(i).unwrap(), | ||
205 | } | ||
206 | }) | ||
207 | } | ||
208 | } | ||
209 | |||
210 | fn has_short_text(kind: SyntaxKind) -> bool { | ||
211 | match kind { | ||
212 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, | ||
213 | _ => false, | ||
214 | } | ||
215 | } | ||
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs index 280bedd78..affd7f9c7 100644 --- a/crates/ra_syntax/src/yellow/syntax_text.rs +++ b/crates/ra_syntax/src/yellow/syntax_text.rs | |||
@@ -25,7 +25,7 @@ impl<'a> SyntaxText<'a> { | |||
25 | let range = self.range; | 25 | let range = self.range; |
26 | preorder(self.node) | 26 | preorder(self.node) |
27 | .filter_map(move |node| { | 27 | .filter_map(move |node| { |
28 | let text = node.leaf_text_ref()?; | 28 | let text = node.leaf_text()?; |
29 | let range = intersect(range, node.range())?; | 29 | let range = intersect(range, node.range())?; |
30 | let range = range - node.range().start(); | 30 | let range = range - node.range().start(); |
31 | Some(&text[range]) | 31 | Some(&text[range]) |