diff options
author | Aleksey Kladov <[email protected]> | 2018-08-11 10:28:59 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-11 10:28:59 +0100 |
commit | 7afd84febc76a75a3ed1be75c57ff35d7b8b3de6 (patch) | |
tree | 76eb2de7efc569c39cc721b7be298490b9647e0b /crates/libsyntax2/src | |
parent | d5119133fc03694c6644cac9e307d1d496fc9bf2 (diff) |
visitor
Diffstat (limited to 'crates/libsyntax2/src')
-rw-r--r-- | crates/libsyntax2/src/algo/mod.rs | 1 | ||||
-rw-r--r-- | crates/libsyntax2/src/algo/visit.rs | 52 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs | 80 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs.tera | 8 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/mod.rs | 9 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 28 | ||||
-rw-r--r-- | crates/libsyntax2/src/yellow/syntax.rs | 6 |
7 files changed, 107 insertions, 77 deletions
diff --git a/crates/libsyntax2/src/algo/mod.rs b/crates/libsyntax2/src/algo/mod.rs index d2de70fd4..263b58d97 100644 --- a/crates/libsyntax2/src/algo/mod.rs +++ b/crates/libsyntax2/src/algo/mod.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | pub mod walk; | 1 | pub mod walk; |
2 | pub mod visit; | ||
2 | 3 | ||
3 | use {SyntaxNodeRef, TextUnit, TextRange}; | 4 | use {SyntaxNodeRef, TextUnit, TextRange}; |
4 | 5 | ||
diff --git a/crates/libsyntax2/src/algo/visit.rs b/crates/libsyntax2/src/algo/visit.rs new file mode 100644 index 000000000..dc5afa5a9 --- /dev/null +++ b/crates/libsyntax2/src/algo/visit.rs | |||
@@ -0,0 +1,52 @@ | |||
1 | use std::marker::PhantomData; | ||
2 | use {SyntaxNodeRef, AstNode, SyntaxRoot}; | ||
3 | |||
4 | |||
5 | pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { | ||
6 | EmptyVisitor { ph: PhantomData } | ||
7 | } | ||
8 | |||
9 | pub trait Visitor<'a>: Sized { | ||
10 | type Output; | ||
11 | fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>; | ||
12 | fn visit<N, F>(self, f: F) -> Vis<Self, N, F> | ||
13 | where N: AstNode<&'a SyntaxRoot>, | ||
14 | F: FnOnce(N) -> Self::Output, | ||
15 | { | ||
16 | Vis { inner: self, f, ph: PhantomData } | ||
17 | } | ||
18 | } | ||
19 | |||
20 | #[derive(Debug)] | ||
21 | struct EmptyVisitor<T> { | ||
22 | ph: PhantomData<fn() -> T> | ||
23 | } | ||
24 | |||
25 | impl<'a, T> Visitor<'a> for EmptyVisitor<T> { | ||
26 | type Output = T; | ||
27 | |||
28 | fn accept(self, _node: SyntaxNodeRef<'a>) -> Option<T> { | ||
29 | None | ||
30 | } | ||
31 | } | ||
32 | |||
33 | #[derive(Debug)] | ||
34 | pub struct Vis<V, N, F> { | ||
35 | inner: V, | ||
36 | f: F, | ||
37 | ph: PhantomData<fn(N)>, | ||
38 | } | ||
39 | |||
40 | impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F> | ||
41 | where | ||
42 | V: Visitor<'a>, | ||
43 | N: AstNode<&'a SyntaxRoot>, | ||
44 | F: FnOnce(N) -> <V as Visitor<'a>>::Output, | ||
45 | { | ||
46 | type Output = <V as Visitor<'a>>::Output; | ||
47 | |||
48 | fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output> { | ||
49 | let Vis { inner, f, .. } = self; | ||
50 | inner.accept(node).or_else(|| N::cast(node).map(f)) | ||
51 | } | ||
52 | } | ||
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 7a2a9c7d4..a4b116941 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use { | 2 | use { |
3 | ast, | ||
3 | SyntaxNode, SyntaxRoot, TreeRoot, AstNode, | 4 | SyntaxNode, SyntaxRoot, TreeRoot, AstNode, |
4 | SyntaxKind::*, | 5 | SyntaxKind::*, |
5 | }; | 6 | }; |
6 | 7 | ||
8 | // ConstItem | ||
7 | #[derive(Debug, Clone, Copy)] | 9 | #[derive(Debug, Clone, Copy)] |
8 | pub struct ConstItem<R: TreeRoot = Arc<SyntaxRoot>> { | 10 | pub struct ConstItem<R: TreeRoot = Arc<SyntaxRoot>> { |
9 | syntax: SyntaxNode<R>, | 11 | syntax: SyntaxNode<R>, |
@@ -19,15 +21,10 @@ impl<R: TreeRoot> AstNode<R> for ConstItem<R> { | |||
19 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 21 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
20 | } | 22 | } |
21 | 23 | ||
22 | impl<R: TreeRoot> ConstItem<R> { | 24 | impl<R: TreeRoot> ast::NameOwner<R> for ConstItem<R> {} |
23 | pub fn name(&self) -> Option<Name<R>> { | 25 | impl<R: TreeRoot> ConstItem<R> {} |
24 | self.syntax() | ||
25 | .children() | ||
26 | .filter_map(Name::cast) | ||
27 | .next() | ||
28 | } | ||
29 | } | ||
30 | 26 | ||
27 | // Enum | ||
31 | #[derive(Debug, Clone, Copy)] | 28 | #[derive(Debug, Clone, Copy)] |
32 | pub struct Enum<R: TreeRoot = Arc<SyntaxRoot>> { | 29 | pub struct Enum<R: TreeRoot = Arc<SyntaxRoot>> { |
33 | syntax: SyntaxNode<R>, | 30 | syntax: SyntaxNode<R>, |
@@ -43,15 +40,10 @@ impl<R: TreeRoot> AstNode<R> for Enum<R> { | |||
43 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 40 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
44 | } | 41 | } |
45 | 42 | ||
46 | impl<R: TreeRoot> Enum<R> { | 43 | impl<R: TreeRoot> ast::NameOwner<R> for Enum<R> {} |
47 | pub fn name(&self) -> Option<Name<R>> { | 44 | impl<R: TreeRoot> Enum<R> {} |
48 | self.syntax() | ||
49 | .children() | ||
50 | .filter_map(Name::cast) | ||
51 | .next() | ||
52 | } | ||
53 | } | ||
54 | 45 | ||
46 | // File | ||
55 | #[derive(Debug, Clone, Copy)] | 47 | #[derive(Debug, Clone, Copy)] |
56 | pub struct File<R: TreeRoot = Arc<SyntaxRoot>> { | 48 | pub struct File<R: TreeRoot = Arc<SyntaxRoot>> { |
57 | syntax: SyntaxNode<R>, | 49 | syntax: SyntaxNode<R>, |
@@ -75,6 +67,7 @@ impl<R: TreeRoot> File<R> { | |||
75 | } | 67 | } |
76 | } | 68 | } |
77 | 69 | ||
70 | // Function | ||
78 | #[derive(Debug, Clone, Copy)] | 71 | #[derive(Debug, Clone, Copy)] |
79 | pub struct Function<R: TreeRoot = Arc<SyntaxRoot>> { | 72 | pub struct Function<R: TreeRoot = Arc<SyntaxRoot>> { |
80 | syntax: SyntaxNode<R>, | 73 | syntax: SyntaxNode<R>, |
@@ -90,15 +83,10 @@ impl<R: TreeRoot> AstNode<R> for Function<R> { | |||
90 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 83 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
91 | } | 84 | } |
92 | 85 | ||
93 | impl<R: TreeRoot> Function<R> { | 86 | impl<R: TreeRoot> ast::NameOwner<R> for Function<R> {} |
94 | pub fn name(&self) -> Option<Name<R>> { | 87 | impl<R: TreeRoot> Function<R> {} |
95 | self.syntax() | ||
96 | .children() | ||
97 | .filter_map(Name::cast) | ||
98 | .next() | ||
99 | } | ||
100 | } | ||
101 | 88 | ||
89 | // Module | ||
102 | #[derive(Debug, Clone, Copy)] | 90 | #[derive(Debug, Clone, Copy)] |
103 | pub struct Module<R: TreeRoot = Arc<SyntaxRoot>> { | 91 | pub struct Module<R: TreeRoot = Arc<SyntaxRoot>> { |
104 | syntax: SyntaxNode<R>, | 92 | syntax: SyntaxNode<R>, |
@@ -114,15 +102,10 @@ impl<R: TreeRoot> AstNode<R> for Module<R> { | |||
114 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 102 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
115 | } | 103 | } |
116 | 104 | ||
117 | impl<R: TreeRoot> Module<R> { | 105 | impl<R: TreeRoot> ast::NameOwner<R> for Module<R> {} |
118 | pub fn name(&self) -> Option<Name<R>> { | 106 | impl<R: TreeRoot> Module<R> {} |
119 | self.syntax() | ||
120 | .children() | ||
121 | .filter_map(Name::cast) | ||
122 | .next() | ||
123 | } | ||
124 | } | ||
125 | 107 | ||
108 | // Name | ||
126 | #[derive(Debug, Clone, Copy)] | 109 | #[derive(Debug, Clone, Copy)] |
127 | pub struct Name<R: TreeRoot = Arc<SyntaxRoot>> { | 110 | pub struct Name<R: TreeRoot = Arc<SyntaxRoot>> { |
128 | syntax: SyntaxNode<R>, | 111 | syntax: SyntaxNode<R>, |
@@ -140,6 +123,7 @@ impl<R: TreeRoot> AstNode<R> for Name<R> { | |||
140 | 123 | ||
141 | impl<R: TreeRoot> Name<R> {} | 124 | impl<R: TreeRoot> Name<R> {} |
142 | 125 | ||
126 | // StaticItem | ||
143 | #[derive(Debug, Clone, Copy)] | 127 | #[derive(Debug, Clone, Copy)] |
144 | pub struct StaticItem<R: TreeRoot = Arc<SyntaxRoot>> { | 128 | pub struct StaticItem<R: TreeRoot = Arc<SyntaxRoot>> { |
145 | syntax: SyntaxNode<R>, | 129 | syntax: SyntaxNode<R>, |
@@ -155,15 +139,10 @@ impl<R: TreeRoot> AstNode<R> for StaticItem<R> { | |||
155 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 139 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
156 | } | 140 | } |
157 | 141 | ||
158 | impl<R: TreeRoot> StaticItem<R> { | 142 | impl<R: TreeRoot> ast::NameOwner<R> for StaticItem<R> {} |
159 | pub fn name(&self) -> Option<Name<R>> { | 143 | impl<R: TreeRoot> StaticItem<R> {} |
160 | self.syntax() | ||
161 | .children() | ||
162 | .filter_map(Name::cast) | ||
163 | .next() | ||
164 | } | ||
165 | } | ||
166 | 144 | ||
145 | // Struct | ||
167 | #[derive(Debug, Clone, Copy)] | 146 | #[derive(Debug, Clone, Copy)] |
168 | pub struct Struct<R: TreeRoot = Arc<SyntaxRoot>> { | 147 | pub struct Struct<R: TreeRoot = Arc<SyntaxRoot>> { |
169 | syntax: SyntaxNode<R>, | 148 | syntax: SyntaxNode<R>, |
@@ -179,15 +158,10 @@ impl<R: TreeRoot> AstNode<R> for Struct<R> { | |||
179 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 158 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
180 | } | 159 | } |
181 | 160 | ||
182 | impl<R: TreeRoot> Struct<R> { | 161 | impl<R: TreeRoot> ast::NameOwner<R> for Struct<R> {} |
183 | pub fn name(&self) -> Option<Name<R>> { | 162 | impl<R: TreeRoot> Struct<R> {} |
184 | self.syntax() | ||
185 | .children() | ||
186 | .filter_map(Name::cast) | ||
187 | .next() | ||
188 | } | ||
189 | } | ||
190 | 163 | ||
164 | // Trait | ||
191 | #[derive(Debug, Clone, Copy)] | 165 | #[derive(Debug, Clone, Copy)] |
192 | pub struct Trait<R: TreeRoot = Arc<SyntaxRoot>> { | 166 | pub struct Trait<R: TreeRoot = Arc<SyntaxRoot>> { |
193 | syntax: SyntaxNode<R>, | 167 | syntax: SyntaxNode<R>, |
@@ -203,12 +177,6 @@ impl<R: TreeRoot> AstNode<R> for Trait<R> { | |||
203 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 177 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
204 | } | 178 | } |
205 | 179 | ||
206 | impl<R: TreeRoot> Trait<R> { | 180 | impl<R: TreeRoot> ast::NameOwner<R> for Trait<R> {} |
207 | pub fn name(&self) -> Option<Name<R>> { | 181 | impl<R: TreeRoot> Trait<R> {} |
208 | self.syntax() | ||
209 | .children() | ||
210 | .filter_map(Name::cast) | ||
211 | .next() | ||
212 | } | ||
213 | } | ||
214 | 182 | ||
diff --git a/crates/libsyntax2/src/ast/generated.rs.tera b/crates/libsyntax2/src/ast/generated.rs.tera index 86b8b05d1..3d79b5543 100644 --- a/crates/libsyntax2/src/ast/generated.rs.tera +++ b/crates/libsyntax2/src/ast/generated.rs.tera | |||
@@ -1,9 +1,11 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use { | 2 | use { |
3 | ast, | ||
3 | SyntaxNode, SyntaxRoot, TreeRoot, AstNode, | 4 | SyntaxNode, SyntaxRoot, TreeRoot, AstNode, |
4 | SyntaxKind::*, | 5 | SyntaxKind::*, |
5 | }; | 6 | }; |
6 | {% for node, methods in ast %} | 7 | {% for node, methods in ast %} |
8 | // {{ node }} | ||
7 | #[derive(Debug, Clone, Copy)] | 9 | #[derive(Debug, Clone, Copy)] |
8 | pub struct {{ node }}<R: TreeRoot = Arc<SyntaxRoot>> { | 10 | pub struct {{ node }}<R: TreeRoot = Arc<SyntaxRoot>> { |
9 | syntax: SyntaxNode<R>, | 11 | syntax: SyntaxNode<R>, |
@@ -19,6 +21,12 @@ impl<R: TreeRoot> AstNode<R> for {{ node }}<R> { | |||
19 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } | 21 | fn syntax(&self) -> &SyntaxNode<R> { &self.syntax } |
20 | } | 22 | } |
21 | 23 | ||
24 | {% if methods.traits -%} | ||
25 | {%- for t in methods.traits -%} | ||
26 | impl<R: TreeRoot> ast::{{ t }}<R> for {{ node }}<R> {} | ||
27 | {% endfor -%} | ||
28 | {%- endif -%} | ||
29 | |||
22 | impl<R: TreeRoot> {{ node }}<R> { | 30 | impl<R: TreeRoot> {{ node }}<R> { |
23 | {%- if methods.collections -%} | 31 | {%- if methods.collections -%} |
24 | {%- for m in methods.collections -%} | 32 | {%- for m in methods.collections -%} |
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index 7d3cdb93d..56bc099fe 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs | |||
@@ -12,6 +12,15 @@ pub trait AstNode<R: TreeRoot>: Sized { | |||
12 | fn syntax(&self) -> &SyntaxNode<R>; | 12 | fn syntax(&self) -> &SyntaxNode<R>; |
13 | } | 13 | } |
14 | 14 | ||
15 | pub trait NameOwner<R: TreeRoot>: AstNode<R> { | ||
16 | fn name(&self) -> Option<Name<R>> { | ||
17 | self.syntax() | ||
18 | .children() | ||
19 | .filter_map(Name::cast) | ||
20 | .next() | ||
21 | } | ||
22 | } | ||
23 | |||
15 | impl File<Arc<SyntaxRoot>> { | 24 | impl File<Arc<SyntaxRoot>> { |
16 | pub fn parse(text: &str) -> Self { | 25 | pub fn parse(text: &str) -> Self { |
17 | File::cast(::parse(text)).unwrap() | 26 | File::cast(::parse(text)).unwrap() |
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index c9470d4fa..3fe8fdf0b 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -220,39 +220,25 @@ Grammar( | |||
220 | ] | 220 | ] |
221 | ), | 221 | ), |
222 | "Function": ( | 222 | "Function": ( |
223 | options: [ | 223 | traits: ["NameOwner"] |
224 | ["name", "Name"] | ||
225 | ] | ||
226 | ), | 224 | ), |
227 | "Struct": ( | 225 | "Struct": ( |
228 | options: [ | 226 | traits: ["NameOwner"] |
229 | ["name", "Name"] | ||
230 | ] | ||
231 | ), | 227 | ), |
232 | "Enum": ( | 228 | "Enum": ( |
233 | options: [ | 229 | traits: ["NameOwner"] |
234 | ["name", "Name"] | ||
235 | ] | ||
236 | ), | 230 | ), |
237 | "Trait": ( | 231 | "Trait": ( |
238 | options: [ | 232 | traits: ["NameOwner"] |
239 | ["name", "Name"] | ||
240 | ] | ||
241 | ), | 233 | ), |
242 | "Module": ( | 234 | "Module": ( |
243 | options: [ | 235 | traits: ["NameOwner"] |
244 | ["name", "Name"] | ||
245 | ] | ||
246 | ), | 236 | ), |
247 | "ConstItem": ( | 237 | "ConstItem": ( |
248 | options: [ | 238 | traits: ["NameOwner"] |
249 | ["name", "Name"] | ||
250 | ] | ||
251 | ), | 239 | ), |
252 | "StaticItem": ( | 240 | "StaticItem": ( |
253 | options: [ | 241 | traits: ["NameOwner"] |
254 | ["name", "Name"] | ||
255 | ] | ||
256 | ), | 242 | ), |
257 | "Name": (), | 243 | "Name": (), |
258 | }, | 244 | }, |
diff --git a/crates/libsyntax2/src/yellow/syntax.rs b/crates/libsyntax2/src/yellow/syntax.rs index 6e33310f1..a22275ed9 100644 --- a/crates/libsyntax2/src/yellow/syntax.rs +++ b/crates/libsyntax2/src/yellow/syntax.rs | |||
@@ -28,6 +28,12 @@ impl<R: TreeRoot> Eq for SyntaxNode<R> {} | |||
28 | 28 | ||
29 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; | 29 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; |
30 | 30 | ||
31 | #[test] | ||
32 | fn syntax_node_ref_is_copy() { | ||
33 | fn assert_copy<T: Copy>(){} | ||
34 | assert_copy::<SyntaxNodeRef>() | ||
35 | } | ||
36 | |||
31 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] | 37 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
32 | pub struct SyntaxError { | 38 | pub struct SyntaxError { |
33 | pub msg: String, | 39 | pub msg: String, |