aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-10-02 15:07:12 +0100
committerAleksey Kladov <[email protected]>2018-10-02 15:09:23 +0100
commita261a1836ba02a1c091c5165795dc165ca399a87 (patch)
treee8bab3ea497a8e7207a24e481361bdd56ed81eaa
parentcd9c5f4ab205e092b87be6affe6d7e78d877dbf0 (diff)
Move to rowan for syntax tree impl
-rw-r--r--Cargo.lock14
-rw-r--r--Cargo.toml1
-rw-r--r--crates/ra_syntax/Cargo.toml3
-rw-r--r--crates/ra_syntax/src/ast/mod.rs13
-rw-r--r--crates/ra_syntax/src/lib.rs13
-rw-r--r--crates/ra_syntax/src/reparsing.rs8
-rw-r--r--crates/ra_syntax/src/utils.rs4
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs32
-rw-r--r--crates/ra_syntax/src/yellow/green.rs90
-rw-r--r--crates/ra_syntax/src/yellow/mod.rs174
-rw-r--r--crates/ra_syntax/src/yellow/red.rs113
-rw-r--r--crates/ra_syntax/src/yellow/syntax.rs215
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs2
13 files changed, 150 insertions, 532 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 815c97483..fb1609e44 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -602,9 +602,8 @@ dependencies = [
602 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 602 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
603 "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", 603 "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
604 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 604 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
605 "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 605 "rowan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
606 "test_utils 0.1.0", 606 "test_utils 0.1.0",
607 "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
608 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 607 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
609 "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 608 "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
610] 609]
@@ -714,6 +713,16 @@ dependencies = [
714] 713]
715 714
716[[package]] 715[[package]]
716name = "rowan"
717version = "0.1.0"
718source = "registry+https://github.com/rust-lang/crates.io-index"
719dependencies = [
720 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
721 "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
722 "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
723]
724
725[[package]]
717name = "rustc-demangle" 726name = "rustc-demangle"
718version = "0.1.9" 727version = "0.1.9"
719source = "registry+https://github.com/rust-lang/crates.io-index" 728source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1230,6 +1239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1230"checksum relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e614f96449605730b4f7ad2c019e88c1652d730634b4eba07b810801856635e3" 1239"checksum relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e614f96449605730b4f7ad2c019e88c1652d730634b4eba07b810801856635e3"
1231"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1240"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
1232"checksum ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fa11b7a38511d46ff1959ae46ebb60bd8a746f17bdd0206b4c8de7559ac47b" 1241"checksum ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fa11b7a38511d46ff1959ae46ebb60bd8a746f17bdd0206b4c8de7559ac47b"
1242"checksum rowan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a1a7366ece9deee5e7df8316a136d585d5c5042854c2297f7f1aee3014c9130"
1233"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" 1243"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
1234"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1244"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1235"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" 1245"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
diff --git a/Cargo.toml b/Cargo.toml
index 5cfc064b5..8e4e84729 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,6 @@
1[workspace] 1[workspace]
2members = [ "crates/*" ] 2members = [ "crates/*" ]
3exclude = [ "crates/rowan"]
3 4
4[profile.release] 5[profile.release]
5debug = true 6debug = true
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]
8unicode-xid = "0.1.0" 8unicode-xid = "0.1.0"
9text_unit = "0.1.4"
10itertools = "0.7.8" 9itertools = "0.7.8"
11drop_bomb = "0.1.4" 10drop_bomb = "0.1.4"
12parking_lot = "0.6.0" 11parking_lot = "0.6.0"
13smol_str = "0.1.6" 12rowan = "0.1.0"
14 13
15[dev-dependencies] 14[dev-dependencies]
16test_utils = { path = "../test_utils" } 15test_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;
3use std::marker::PhantomData; 3use std::marker::PhantomData;
4 4
5use itertools::Itertools; 5use itertools::Itertools;
6use smol_str::SmolStr;
7 6
8use { 7use {
9 SyntaxNodeRef, SyntaxKind::*, 8 SmolStr, SyntaxNodeRef, SyntaxKind::*,
10 yellow::{RefRoot, SyntaxNodeChildren}, 9 yellow::{RefRoot, SyntaxNodeChildren},
11}; 10};
12pub use self::generated::*; 11pub 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
97impl<'a> Lifetime<'a> { 96impl<'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;
24extern crate unicode_xid; 24extern crate unicode_xid;
25extern crate drop_bomb; 25extern crate drop_bomb;
26extern crate parking_lot; 26extern crate parking_lot;
27extern crate smol_str; 27extern crate rowan;
28extern crate text_unit;
29 28
30#[cfg(test)] 29#[cfg(test)]
31#[macro_use] 30#[macro_use]
@@ -48,8 +47,7 @@ pub mod utils;
48pub mod text_utils; 47pub mod text_utils;
49 48
50pub use { 49pub 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
60use { 58use {
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
69impl File { 67impl 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 @@
1use algo; 1use algo;
2use grammar; 2use grammar;
3use lexer::{tokenize, Token}; 3use lexer::{tokenize, Token};
4use text_unit::{TextRange, TextUnit}; 4use yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError};
5use yellow::{self, SyntaxNodeRef, GreenNode, SyntaxError};
6use parser_impl; 5use parser_impl;
7use parser_api::Parser; 6use parser_api::Parser;
8use { 7use {
8 TextUnit, TextRange,
9 SyntaxKind::*, 9 SyntaxKind::*,
10}; 10};
11use text_utils::replace_range; 11use 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 @@
1use std::fmt::Write; 1use std::fmt::Write;
2use { 2use {
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.
8pub fn dump_tree(syntax: SyntaxNodeRef) -> String { 8pub 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 @@
1use rowan::GreenNodeBuilder;
1use { 2use {
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
7pub(crate) struct GreenBuilder<'a> { 8pub(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
15impl<'a> Sink<'a> for GreenBuilder<'a> { 15impl<'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 @@
1use std::sync::Arc;
2
3use smol_str::SmolStr;
4
5use {SyntaxKind, TextUnit};
6
7#[derive(Clone, Debug)]
8pub(crate) enum GreenNode {
9 Leaf {
10 kind: SyntaxKind,
11 text: SmolStr,
12 },
13 Branch(Arc<GreenBranch>),
14}
15
16impl 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)]
55pub(crate) struct GreenBranch {
56 text_len: TextUnit,
57 kind: SyntaxKind,
58 children: Box<[GreenNode]>,
59}
60
61impl 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]
85fn 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 @@
1mod builder; 1mod builder;
2mod green;
3mod red;
4mod syntax;
5mod syntax_text; 2mod syntax_text;
6 3
7use std::{ 4use std::{
8 sync::Arc, 5 fmt,
9 ptr, 6 hash::{Hash, Hasher},
10};
11pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren};
12pub(crate) use self::{
13 builder::GreenBuilder,
14 green::GreenNode,
15 red::RedNode,
16 syntax_text::SyntaxText,
17}; 7};
8use rowan::Types;
9use {SyntaxKind, TextUnit, TextRange, SmolStr};
10use self::syntax_text::SyntaxText;
18 11
19#[derive(Debug)] 12pub use rowan::{TreeRoot};
20pub struct SyntaxRoot { 13pub(crate) use self::builder::GreenBuilder;
21 red: RedNode, 14
22 pub(crate) errors: Vec<SyntaxError>, 15#[derive(Debug, Clone, Copy)]
16pub enum RaTypes {}
17impl Types for RaTypes {
18 type Kind = SyntaxKind;
19 type RootData = Vec<SyntaxError>;
23} 20}
24 21
25pub trait TreeRoot: Clone + Send + Sync { 22pub type OwnedRoot = ::rowan::OwnedRoot<RaTypes>;
26 fn borrowed(&self) -> RefRoot; 23pub type RefRoot<'a> = ::rowan::RefRoot<'a, RaTypes>;
27 fn owned(&self) -> OwnedRoot; 24
25pub 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; 28pub struct SyntaxError {
29 pub msg: String,
30 pub offset: TextUnit,
31} 31}
32#[derive(Clone, Debug)]
33pub struct OwnedRoot(Arc<SyntaxRoot>);
34#[derive(Clone, Copy, Debug)]
35pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection
36 32
37impl<'a> RefRoot<'a> { 33#[derive(Clone, Copy)]
38 fn syntax_root(&self) -> &'a SyntaxRoot { 34pub struct SyntaxNode<R: TreeRoot<RaTypes> = OwnedRoot>(
39 self.0.syntax_root() 35 ::rowan::SyntaxNode<RaTypes, R>,
36);
37pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
38
39impl<R1, R2> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2>
40where
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
43impl TreeRoot for OwnedRoot { 49impl<R: TreeRoot<RaTypes>> Eq for SyntaxNode<R> {}
44 fn borrowed(&self) -> RefRoot { 50impl<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 { 56impl 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}
61impl<'a> SyntaxNode<RefRoot<'a>> {
62 pub fn leaf_text(self) -> Option<&'a SmolStr> {
63 self.0.leaf_text()
53 } 64 }
54} 65}
55 66
56impl<'a> TreeRoot for RefRoot<'a> { 67impl<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
68impl SyntaxRoot { 112impl<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)]
78pub(crate) struct RedPtr(ptr::NonNull<RedNode>); 123pub struct SyntaxNodeChildren<R: TreeRoot<RaTypes>>(
79 124 ::rowan::SyntaxNodeChildren<RaTypes, R>
80unsafe impl Send for RedPtr {} 125);
81
82unsafe impl Sync for RedPtr {}
83 126
84impl RedPtr { 127impl<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
95fn assert_send_sync() { 136fn 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 @@
1use parking_lot::RwLock;
2use {yellow::{GreenNode, RedPtr}, TextUnit};
3
4#[derive(Debug)]
5pub(crate) struct RedNode {
6 green: GreenNode,
7 parent: Option<ParentData>,
8 children: RwLock<Box<[RedChild]>>,
9}
10
11#[derive(Debug)]
12enum RedChild {
13 Zigot(TextUnit),
14 Child(RedNode)
15}
16
17impl 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)]
33struct ParentData {
34 parent: RedPtr,
35 start_offset: TextUnit,
36 index_in_parent: usize,
37}
38
39impl 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 @@
1use std::{
2 fmt, sync::Arc,
3 hash::{Hasher, Hash},
4 ops::Range,
5};
6
7use smol_str::SmolStr;
8
9use {
10 yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText},
11 SyntaxKind::{self, *},
12 TextRange, TextUnit,
13};
14
15
16#[derive(Clone, Copy)]
17pub 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
24unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {}
25unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {}
26
27impl<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
33impl<R: TreeRoot> Eq for SyntaxNode<R> {}
34impl<R: TreeRoot> Hash for SyntaxNode<R> {
35 fn hash<H: Hasher>(&self, state: &mut H) {
36 self.red.hash(state)
37 }
38}
39
40pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
41
42#[test]
43fn 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)]
49pub struct SyntaxError {
50 pub msg: String,
51 pub offset: TextUnit,
52}
53
54impl 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
62impl<'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
69impl<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
180impl<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)]
191pub struct SyntaxNodeChildren<R: TreeRoot> {
192 parent: SyntaxNode<R>,
193 iter: Range<usize>,
194}
195
196impl<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
210fn 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])