summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stag/src/main.rs72
-rw-r--r--stag/src/stag.scm538
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 @@
1use std::collections::VecDeque;
2
3use serde::Deserialize; 1use serde::Deserialize;
4use serde::Serialize; 2use serde::Serialize;
5use tree_sitter::Parser; 3use tree_sitter::Parser;
@@ -19,11 +17,14 @@ use petgraph::{graph::NodeIndex, visit::EdgeRef, Direction, Graph};
19 17
20fn main() { 18fn 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
60fn range_to_value(value: &tree_sitter::Range) -> Value { 70fn range_to_value(value: &tree_sitter::Range) -> Value {
@@ -111,11 +121,12 @@ fn is_ref(node: &tree_sitter_graph::graph::GraphNode) -> bool {
111 121
112pub struct ScopeShorthand; 122pub struct ScopeShorthand;
113 123
124#[allow(unused_must_use)]
114impl Function for ScopeShorthand { 125impl 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
141pub struct DefShorthand; 152pub struct DefShorthand;
142 153
154#[allow(unused_must_use)]
143impl Function for DefShorthand { 155impl 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
179pub struct RefShortHand; 201pub struct RefShortHand;
180 202
203#[allow(unused_must_use)]
181impl Function for RefShortHand { 204impl 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