diff options
-rw-r--r-- | stag/src/main.rs | 72 | ||||
-rw-r--r-- | stag/src/stag.scm | 538 |
2 files changed, 579 insertions, 31 deletions
diff --git a/stag/src/main.rs b/stag/src/main.rs index eae6fe9..1945a03 100644 --- a/stag/src/main.rs +++ b/stag/src/main.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | use std::collections::VecDeque; | ||
2 | |||
3 | use serde::Deserialize; | 1 | use serde::Deserialize; |
4 | use serde::Serialize; | 2 | use serde::Serialize; |
5 | use tree_sitter::Parser; | 3 | use tree_sitter::Parser; |
@@ -19,11 +17,14 @@ use petgraph::{graph::NodeIndex, visit::EdgeRef, Direction, Graph}; | |||
19 | 17 | ||
20 | fn main() { | 18 | fn main() { |
21 | let scopes = std::fs::read_to_string("src/stag.scm").unwrap(); | 19 | let scopes = std::fs::read_to_string("src/stag.scm").unwrap(); |
22 | let src = r#"fn main() { | 20 | let src = r#" |
23 | let a = 3; | 21 | fn main() { |
24 | let b = 4; | 22 | let x = 2; |
25 | a + b | 23 | let a = 5; |
26 | } | 24 | if let _ = z { |
25 | a[x]; | ||
26 | } | ||
27 | } | ||
27 | "#; | 28 | "#; |
28 | 29 | ||
29 | let mut parser = Parser::new(); | 30 | let mut parser = Parser::new(); |
@@ -55,6 +56,15 @@ fn main() { | |||
55 | sg = build_scope_graph(graph, sg); | 56 | sg = build_scope_graph(graph, sg); |
56 | 57 | ||
57 | println!("{:#?}", sg); | 58 | println!("{:#?}", sg); |
59 | |||
60 | for e in sg | ||
61 | .graph | ||
62 | .raw_edges() | ||
63 | .iter() | ||
64 | .filter(|e| e.weight == EdgeKind::RefToDef) | ||
65 | { | ||
66 | println!("{:?} -> {:?}", e.source(), e.target()); | ||
67 | } | ||
58 | } | 68 | } |
59 | 69 | ||
60 | fn range_to_value(value: &tree_sitter::Range) -> Value { | 70 | fn range_to_value(value: &tree_sitter::Range) -> Value { |
@@ -111,11 +121,12 @@ fn is_ref(node: &tree_sitter_graph::graph::GraphNode) -> bool { | |||
111 | 121 | ||
112 | pub struct ScopeShorthand; | 122 | pub struct ScopeShorthand; |
113 | 123 | ||
124 | #[allow(unused_must_use)] | ||
114 | impl Function for ScopeShorthand { | 125 | impl Function for ScopeShorthand { |
115 | fn call( | 126 | fn call( |
116 | &self, | 127 | &self, |
117 | graph: &mut tree_sitter_graph::graph::Graph, | 128 | graph: &mut tree_sitter_graph::graph::Graph, |
118 | source: &str, | 129 | _source: &str, |
119 | parameters: &mut dyn tree_sitter_graph::functions::Parameters, | 130 | parameters: &mut dyn tree_sitter_graph::functions::Parameters, |
120 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { | 131 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { |
121 | let target_range = parameters.param()?; | 132 | let target_range = parameters.param()?; |
@@ -140,6 +151,7 @@ impl Function for ScopeShorthand { | |||
140 | 151 | ||
141 | pub struct DefShorthand; | 152 | pub struct DefShorthand; |
142 | 153 | ||
154 | #[allow(unused_must_use)] | ||
143 | impl Function for DefShorthand { | 155 | impl Function for DefShorthand { |
144 | fn call( | 156 | fn call( |
145 | &self, | 157 | &self, |
@@ -149,6 +161,10 @@ impl Function for DefShorthand { | |||
149 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { | 161 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { |
150 | let target_node = parameters.param()?.into_syntax_node_ref()?; | 162 | let target_node = parameters.param()?.into_syntax_node_ref()?; |
151 | let ts_node = graph[target_node]; | 163 | let ts_node = graph[target_node]; |
164 | let symbol = parameters | ||
165 | .param() | ||
166 | .and_then(|p| p.as_str().map(ToOwned::to_owned)) | ||
167 | .ok(); | ||
152 | parameters.finish()?; | 168 | parameters.finish()?; |
153 | 169 | ||
154 | let graph_node = graph.add_graph_node(); | 170 | let graph_node = graph.add_graph_node(); |
@@ -158,6 +174,12 @@ impl Function for DefShorthand { | |||
158 | graph[graph_node] | 174 | graph[graph_node] |
159 | .attributes | 175 | .attributes |
160 | .add::<String>(Identifier::from("scope"), "local".into()); | 176 | .add::<String>(Identifier::from("scope"), "local".into()); |
177 | |||
178 | if let Some(s) = symbol { | ||
179 | graph[graph_node] | ||
180 | .attributes | ||
181 | .add::<String>(Identifier::from("symbol"), s.into()); | ||
182 | } | ||
161 | graph[graph_node].attributes.add::<String>( | 183 | graph[graph_node].attributes.add::<String>( |
162 | Identifier::from("text"), | 184 | Identifier::from("text"), |
163 | source[ts_node.byte_range()].to_string().into(), | 185 | source[ts_node.byte_range()].to_string().into(), |
@@ -178,6 +200,7 @@ impl Function for DefShorthand { | |||
178 | 200 | ||
179 | pub struct RefShortHand; | 201 | pub struct RefShortHand; |
180 | 202 | ||
203 | #[allow(unused_must_use)] | ||
181 | impl Function for RefShortHand { | 204 | impl Function for RefShortHand { |
182 | fn call( | 205 | fn call( |
183 | &self, | 206 | &self, |
@@ -220,17 +243,29 @@ impl Function for CoverRanges { | |||
220 | _source: &str, | 243 | _source: &str, |
221 | parameters: &mut dyn tree_sitter_graph::functions::Parameters, | 244 | parameters: &mut dyn tree_sitter_graph::functions::Parameters, |
222 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { | 245 | ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> { |
223 | let node_a = parameters.param()?.into_syntax_node_ref()?; | 246 | let p1 = parameters.param()?; |
224 | let node_b = parameters.param()?.into_syntax_node_ref()?; | 247 | let p2 = parameters.param()?; |
225 | let ts_node_a = graph[node_a]; | 248 | |
226 | let ts_node_b = graph[node_b]; | 249 | match (p1.is_null(), p2.is_null()) { |
227 | 250 | (true, true) => panic!("all nulls"), | |
228 | let mut range = cover(ts_node_a.range(), ts_node_b.range()); | 251 | (false, true) => return Ok(range_to_value(&graph[p1.into_syntax_node_ref()?].range())), |
229 | while let Ok(param) = parameters.param() { | 252 | (true, false) => return Ok(range_to_value(&graph[p2.into_syntax_node_ref()?].range())), |
230 | range = cover(range, graph[param.into_syntax_node_ref()?].range()) | 253 | (false, false) => { |
231 | } | 254 | let node_a = p1.into_syntax_node_ref()?; |
255 | let node_b = p2.into_syntax_node_ref()?; | ||
256 | let ts_node_a = graph[node_a]; | ||
257 | let ts_node_b = graph[node_b]; | ||
258 | |||
259 | let mut range = cover(ts_node_a.range(), ts_node_b.range()); | ||
260 | while let Ok(param) = parameters.param() { | ||
261 | if !param.is_null() { | ||
262 | range = cover(range, graph[param.into_syntax_node_ref()?].range()) | ||
263 | } | ||
264 | } | ||
232 | 265 | ||
233 | Ok(range_to_value(&range)) | 266 | Ok(range_to_value(&range)) |
267 | } | ||
268 | } | ||
234 | } | 269 | } |
235 | } | 270 | } |
236 | 271 | ||
@@ -739,7 +774,6 @@ fn build_scope_graph( | |||
739 | mut scope_graph: ScopeGraph, | 774 | mut scope_graph: ScopeGraph, |
740 | ) -> ScopeGraph { | 775 | ) -> ScopeGraph { |
741 | let nodes = tsg.iter_nodes().collect::<Vec<_>>(); | 776 | let nodes = tsg.iter_nodes().collect::<Vec<_>>(); |
742 | // insert scopes first | ||
743 | for node in nodes | 777 | for node in nodes |
744 | .iter() | 778 | .iter() |
745 | .map(|node_ref| &tsg[*node_ref]) | 779 | .map(|node_ref| &tsg[*node_ref]) |
diff --git a/stag/src/stag.scm b/stag/src/stag.scm index b6271b8..dc56e74 100644 --- a/stag/src/stag.scm +++ b/stag/src/stag.scm | |||
@@ -1,36 +1,550 @@ | |||
1 | [ | 1 | [(block) |
2 | (block) | ||
3 | (declaration_list) | 2 | (declaration_list) |
4 | (impl_item) | 3 | (impl_item) |
5 | (struct_item) | 4 | |
6 | (enum_item) | 5 | ;; let expressions create scopes |
7 | (union_item) | ||
8 | (type_item) | ||
9 | (trait_item) | ||
10 | (if_expression | 6 | (if_expression |
11 | [(let_condition) | 7 | [(let_condition) |
12 | (let_chain)]) | 8 | (let_chain)]) |
13 | ] @cap | 9 | |
10 | ;; each match arm can bind variables with | ||
11 | ;; patterns, without creating a block scope; | ||
12 | ;; | ||
13 | ;; match _ { | ||
14 | ;; (a, b) => a, | ||
15 | ;; } | ||
16 | ;; | ||
17 | ;; The bindings for a, b are constrained to | ||
18 | ;; the match arm. | ||
19 | (match_arm) | ||
20 | |||
21 | ;; loop labels are defs that are available only | ||
22 | ;; within the scope they create: | ||
23 | ;; | ||
24 | ;; 'outer: loop { | ||
25 | ;; let x = 2; | ||
26 | ;; }; | ||
27 | ;; let y = 2; | ||
28 | ;; | ||
29 | ;; Produces a scope graph like so: | ||
30 | ;; | ||
31 | ;; { | ||
32 | ;; defs: [ y ], | ||
33 | ;; scopes: [ | ||
34 | ;; { | ||
35 | ;; defs: [ 'outer ], | ||
36 | ;; scopes: [ | ||
37 | ;; { | ||
38 | ;; defs: [ x ] | ||
39 | ;; } | ||
40 | ;; ] | ||
41 | ;; } | ||
42 | ;; ] | ||
43 | ;; } | ||
44 | ;; | ||
45 | (loop_expression) | ||
46 | (for_expression) | ||
47 | (while_expression)] @cap | ||
14 | { | 48 | { |
15 | (scope (range @cap)) | 49 | (scope (range @cap)) |
16 | } | 50 | } |
17 | 51 | ||
52 | |||
18 | (function_item | 53 | (function_item |
54 | (identifier) @i | ||
19 | (parameters) @params | 55 | (parameters) @params |
20 | (block) @body) | 56 | (block) @body) |
21 | { | 57 | { |
58 | (def @i "function") | ||
22 | (scope (cover @params @body)) | 59 | (scope (cover @params @body)) |
23 | } | 60 | } |
24 | 61 | ||
25 | 62 | ||
26 | (let_declaration | 63 | ;; impl items can define types and lifetimes: |
27 | pattern: (identifier) @cap) | 64 | ;; |
65 | ;; impl<'a, T> Trait for Struct { .. } | ||
66 | ;; | ||
67 | ;; in order to constrain those to the impl block, | ||
68 | ;; we add a local scope here: | ||
69 | [(struct_item (type_identifier) @i (type_parameters)? @t body: (_) @b) | ||
70 | (union_item (type_identifier) @i (type_parameters)? @t body: (_) @b) | ||
71 | (enum_item (type_identifier) @i (type_parameters)? @t body: (_) @b) | ||
72 | (type_item (type_identifier) @i (type_parameters)? @t type: (_) @b) | ||
73 | (trait_item (type_identifier) @i (type_parameters)? @t body: (_) @b)] | ||
74 | { | ||
75 | (def @i) | ||
76 | (scope (cover @t @b)) | ||
77 | (scope (range @b)) | ||
78 | } | ||
79 | |||
80 | |||
81 | ;; DEFS | ||
82 | ;; ---- | ||
83 | |||
84 | ;; let x = ...; | ||
85 | (let_declaration pattern: (identifier) @cap) | ||
86 | { | ||
87 | (def @cap "variable") | ||
88 | } | ||
89 | |||
90 | ;; if let x = ...; | ||
91 | ;; while let x = ...; | ||
92 | (let_condition (identifier) @cap . "=") | ||
93 | { | ||
94 | (def @cap "variable") | ||
95 | } | ||
96 | |||
97 | ;; let (a, b, ...) = ..; | ||
98 | ;; if let (a, b, ...) = {} | ||
99 | ;; while let (a, b, ...) = {} | ||
100 | ;; match _ { (a, b) => { .. } } | ||
101 | (tuple_pattern (identifier) @cap) | ||
102 | { | ||
103 | (def @cap "variable") | ||
104 | } | ||
105 | |||
106 | ;; Some(a) | ||
107 | (tuple_struct_pattern | ||
108 | type: (_) | ||
109 | (identifier) @cap) | ||
110 | { | ||
111 | (def @cap "variable") | ||
112 | } | ||
113 | |||
114 | ;; let S { field: a } = ..; | ||
115 | (struct_pattern | ||
116 | (field_pattern | ||
117 | (identifier) @cap)) | ||
118 | { | ||
119 | (def @cap "variable") | ||
120 | } | ||
121 | |||
122 | |||
123 | [ | ||
124 | ;; (mut x: T) | ||
125 | (mut_pattern (identifier) @i) | ||
126 | |||
127 | ;; (ref x: T) | ||
128 | (ref_pattern (identifier) @i) | ||
129 | |||
130 | ;; const x = ...; | ||
131 | (const_item (identifier) @i) | ||
132 | |||
133 | ;; static x = ...; | ||
134 | (static_item (identifier) @i)] | ||
135 | { | ||
136 | (def @i "variable") | ||
137 | } | ||
138 | |||
139 | ;; fn _(x: _) | ||
140 | (parameters | ||
141 | (parameter | ||
142 | pattern: (identifier) @cap)) | ||
143 | { | ||
144 | (def @cap) | ||
145 | } | ||
146 | |||
147 | ;; fn _(self) | ||
148 | (parameters | ||
149 | (self_parameter | ||
150 | (self) @cap)) | ||
151 | { | ||
152 | (def @cap) | ||
153 | } | ||
154 | |||
155 | ;; type parameters | ||
156 | (type_parameters | ||
157 | (type_identifier) @cap) | ||
158 | { | ||
159 | (def @cap) | ||
160 | } | ||
161 | (type_parameters | ||
162 | (lifetime) @cap) | ||
163 | { | ||
164 | (def @cap) | ||
165 | } | ||
166 | (constrained_type_parameter | ||
167 | left: (type_identifier) @cap) | ||
168 | { | ||
169 | (def @cap) | ||
170 | } | ||
171 | |||
172 | ;; |x| { ... } | ||
173 | ;; no type | ||
174 | (closure_parameters (identifier) @cap) | ||
175 | { | ||
176 | (def @cap) | ||
177 | } | ||
178 | |||
179 | ;; |x: T| { ... } | ||
180 | ;; with type | ||
181 | (closure_parameters | ||
182 | (parameter | ||
183 | (identifier) @cap)) | ||
184 | { | ||
185 | (def @cap) | ||
186 | } | ||
187 | |||
188 | ;; 'outer: loop { .. } | ||
189 | (loop_expression | ||
190 | (loop_label) @cap) | ||
191 | { | ||
192 | (def @cap) | ||
193 | } | ||
194 | |||
195 | ;; `for` exprs create two defs: a label (if any) and the | ||
196 | ;; loop variable | ||
197 | (for_expression . (identifier) @cap) | ||
198 | { | ||
199 | (def @cap) | ||
200 | } | ||
201 | (for_expression (loop_label) @cap) | ||
28 | { | 202 | { |
29 | (def @cap) | 203 | (def @cap) |
30 | } | 204 | } |
31 | 205 | ||
206 | ;; 'label: while cond { .. } | ||
207 | (while_expression | ||
208 | (loop_label) @cap) | ||
209 | { | ||
210 | (def @cap) | ||
211 | } | ||
32 | 212 | ||
33 | (binary_expression (identifier) @c) { | 213 | ;; struct and union fields |
34 | (ref @c) | 214 | (field_declaration_list |
215 | (field_declaration | ||
216 | (field_identifier) @cap)) | ||
217 | { | ||
218 | (def @cap) | ||
35 | } | 219 | } |
36 | 220 | ||
221 | ;; enum variants | ||
222 | (enum_variant_list | ||
223 | (enum_variant | ||
224 | (identifier) @cap)) | ||
225 | { | ||
226 | (def @cap) | ||
227 | } | ||
228 | |||
229 | ;; mod x; | ||
230 | (mod_item (identifier) @cap) | ||
231 | { | ||
232 | (def @cap) | ||
233 | } | ||
234 | |||
235 | |||
236 | ;; IMPORTS | ||
237 | ;; ------- | ||
238 | |||
239 | ;; use item; | ||
240 | (use_declaration | ||
241 | (identifier) @cap) | ||
242 | { | ||
243 | (def @cap) | ||
244 | } | ||
245 | |||
246 | ;; use path as item; | ||
247 | (use_as_clause | ||
248 | alias: (identifier) @cap) | ||
249 | { | ||
250 | (def @cap) | ||
251 | } | ||
252 | |||
253 | ;; use path::item; | ||
254 | (use_declaration | ||
255 | (scoped_identifier | ||
256 | name: (identifier) @cap)) | ||
257 | { | ||
258 | (def @cap) | ||
259 | } | ||
260 | |||
261 | ;; use module::{member1, member2, member3}; | ||
262 | (use_list | ||
263 | (identifier) @cap) | ||
264 | { | ||
265 | (def @cap) | ||
266 | } | ||
267 | |||
268 | (use_list | ||
269 | (scoped_identifier | ||
270 | name: (identifier) @cap)) | ||
271 | { | ||
272 | (def @cap) | ||
273 | } | ||
274 | |||
275 | |||
276 | ;; REFS | ||
277 | ;; ---- | ||
278 | |||
279 | [ | ||
280 | ;; !x | ||
281 | (unary_expression (identifier) @cap) | ||
282 | ;; &x | ||
283 | (reference_expression (identifier) @cap) | ||
284 | |||
285 | ;; (x) | ||
286 | (parenthesized_expression (identifier) @cap) | ||
287 | |||
288 | ;; x? | ||
289 | (try_expression (identifier) @cap) | ||
290 | |||
291 | ;; a = b | ||
292 | (assignment_expression (identifier) @cap) | ||
293 | |||
294 | ;; a op b | ||
295 | (binary_expression (identifier) @cap) | ||
296 | |||
297 | ;; a op= b | ||
298 | (compound_assignment_expr (identifier) @cap) | ||
299 | |||
300 | ;; a as b | ||
301 | (type_cast_expression (identifier) @cap) | ||
302 | |||
303 | ;; a() | ||
304 | (call_expression (identifier) @cap) | ||
305 | |||
306 | ;; return a | ||
307 | (return_expression (identifier) @cap) | ||
308 | |||
309 | ;; break a | ||
310 | (break_expression (identifier) @cap) | ||
311 | |||
312 | ;; break 'label | ||
313 | (break_expression (loop_label) @cap) | ||
314 | |||
315 | ;; continue 'label; | ||
316 | (continue_expression (loop_label) @cap) | ||
317 | |||
318 | ;; yield x; | ||
319 | (yield_expression (identifier) @cap) | ||
320 | |||
321 | ;; await a | ||
322 | (await_expression (identifier) @cap) | ||
323 | |||
324 | ;; (a, b) | ||
325 | (tuple_expression (identifier) @cap) | ||
326 | |||
327 | ;; a[] | ||
328 | (index_expression (identifier) @cap) | ||
329 | |||
330 | ;; ident; | ||
331 | (expression_statement (identifier) @cap) | ||
332 | |||
333 | ;; a..b | ||
334 | (range_expression (identifier) @cap) | ||
335 | |||
336 | ;; [ident; N] | ||
337 | (array_expression (identifier) @cap) | ||
338 | |||
339 | ;; path::to::item | ||
340 | ;; | ||
341 | ;; `path` is a ref | ||
342 | (scoped_identifier | ||
343 | path: (identifier) @cap) | ||
344 | |||
345 | ;; rhs of let decls | ||
346 | (let_declaration | ||
347 | value: (identifier) @cap) | ||
348 | |||
349 | ;; type T = [T; N] | ||
350 | ;; | ||
351 | ;; N is a ident ref | ||
352 | (array_type | ||
353 | length: (identifier) @cap) | ||
354 | |||
355 | ;; S { _ } | ||
356 | (struct_expression | ||
357 | (type_identifier) @cap) | ||
358 | |||
359 | ;; S { a } | ||
360 | (struct_expression | ||
361 | (field_initializer_list | ||
362 | (shorthand_field_initializer | ||
363 | (identifier) @cap))) | ||
364 | |||
365 | ;; S { a: value } | ||
366 | (struct_expression | ||
367 | (field_initializer_list | ||
368 | (field_initializer | ||
369 | (identifier) @cap))) | ||
370 | |||
371 | ;; S { ..a } | ||
372 | (struct_expression | ||
373 | (field_initializer_list | ||
374 | (base_field_initializer | ||
375 | (identifier) @cap))) | ||
376 | |||
377 | ;; if a {} | ||
378 | (if_expression (identifier) @cap) | ||
379 | |||
380 | ;; for pattern in value {} | ||
381 | ;; | ||
382 | ;; `value` is a ref | ||
383 | (for_expression | ||
384 | value: (identifier) @cap) | ||
385 | |||
386 | ;; while a {} | ||
387 | (while_expression (identifier) @cap) | ||
388 | |||
389 | ;; match a | ||
390 | (match_expression (identifier) @cap) | ||
391 | |||
392 | ;; match _ { | ||
393 | ;; pattern => a, | ||
394 | ;; } | ||
395 | ;; | ||
396 | ;; this `a` is somehow not any expression form | ||
397 | (match_arm (identifier) @cap) | ||
398 | |||
399 | ;; a.b | ||
400 | ;; | ||
401 | ;; `b` is ignored | ||
402 | (field_expression | ||
403 | (identifier) @cap) | ||
404 | |||
405 | ;; { stmt; foo } | ||
406 | (block | ||
407 | (identifier) @cap) | ||
408 | |||
409 | ;; arguments to method calls or function calls | ||
410 | (arguments | ||
411 | (identifier) @cap) | ||
412 | |||
413 | ;; impl S { .. } | ||
414 | (impl_item (type_identifier) @cap) | ||
415 | |||
416 | ;; where T: ... | ||
417 | (where_predicate | ||
418 | left: (type_identifier) @cap) | ||
419 | |||
420 | ;; trait bounds | ||
421 | (trait_bounds | ||
422 | (type_identifier) @cap) | ||
423 | (trait_bounds | ||
424 | (lifetime) @cap) | ||
425 | |||
426 | ;; idents in macros | ||
427 | (token_tree | ||
428 | (identifier) @cap) | ||
429 | |||
430 | |||
431 | ;; types | ||
432 | |||
433 | ;; (T, U) | ||
434 | (tuple_type | ||
435 | (type_identifier) @cap) | ||
436 | |||
437 | ;; &T | ||
438 | (reference_type | ||
439 | (type_identifier) @cap) | ||
440 | |||
441 | ;; &'a T | ||
442 | (reference_type | ||
443 | (lifetime) @cap) | ||
444 | |||
445 | ;; &'a self | ||
446 | (self_parameter | ||
447 | (lifetime) @cap) | ||
448 | |||
449 | ;; *mut T | ||
450 | ;; *const T | ||
451 | (pointer_type | ||
452 | (type_identifier) @cap) | ||
453 | |||
454 | ;; A<_> | ||
455 | (generic_type | ||
456 | (type_identifier) @cap) | ||
457 | |||
458 | ;; _<V> | ||
459 | (type_arguments | ||
460 | (type_identifier) @cap) | ||
461 | (type_arguments | ||
462 | (lifetime) @cap) | ||
463 | |||
464 | ;; T<U = V> | ||
465 | ;; | ||
466 | ;; U is ignored | ||
467 | ;; V is a ref | ||
468 | (type_binding | ||
469 | name: (_) | ||
470 | type: (type_identifier) @cap) | ||
471 | |||
472 | ;; [T] | ||
473 | (array_type | ||
474 | (type_identifier) @cap) | ||
475 | |||
476 | ;; type T = U; | ||
477 | ;; | ||
478 | ;; T is a def | ||
479 | ;; U is a ref | ||
480 | (type_item | ||
481 | name: (_) | ||
482 | type: (type_identifier) @cap) | ||
483 | |||
484 | (function_item | ||
485 | return_type: (type_identifier) @cap) | ||
486 | |||
487 | ;; type refs in params | ||
488 | ;; | ||
489 | ;; fn _(_: T) | ||
490 | (parameters | ||
491 | (parameter | ||
492 | type: (type_identifier) @cap)) | ||
493 | |||
494 | ;; dyn T | ||
495 | (dynamic_type | ||
496 | (type_identifier) @cap) | ||
497 | |||
498 | ;; <T>::call() | ||
499 | (bracketed_type | ||
500 | (type_identifier) @cap) | ||
501 | |||
502 | ;; T as Trait | ||
503 | (qualified_type | ||
504 | (type_identifier) @cap) | ||
505 | |||
506 | ;; module::T | ||
507 | ;; | ||
508 | ;; `module` is a def | ||
509 | ;; `T` is a ref | ||
510 | (scoped_type_identifier | ||
511 | path: (identifier) @cap) | ||
512 | |||
513 | ;; struct _ { field: Type } | ||
514 | ;; `Type` is a ref | ||
515 | (field_declaration | ||
516 | name: (_) | ||
517 | type: (type_identifier) @cap) | ||
518 | |||
519 | ;; Self::foo() | ||
520 | ;; | ||
521 | ;; `foo` can be resolved | ||
522 | (call_expression | ||
523 | (scoped_identifier | ||
524 | (identifier) @_self_type | ||
525 | (identifier) @cap) | ||
526 | (#match? @_self_type "Self")) | ||
527 | |||
528 | ;; self.foo() | ||
529 | ;; | ||
530 | ;; `foo` can be resolved | ||
531 | (call_expression | ||
532 | (field_expression | ||
533 | (self) | ||
534 | (field_identifier) @cap)) | ||
535 | |||
536 | ;; if let _ = a {} | ||
537 | ;; | ||
538 | ;; the ident following the `=` is a ref | ||
539 | ;; the ident preceding the `=` is a def | ||
540 | ;; while let _ = a {} | ||
541 | (let_condition | ||
542 | "=" | ||
543 | . | ||
544 | (identifier) @cap) | ||
545 | ] | ||
546 | { | ||
547 | (ref @cap) | ||
548 | } | ||
549 | |||
550 | |||