···11+mod text_range;
22+use petgraph::{graph::NodeIndex, visit::EdgeRef, Direction, Graph};
33+use serde::{Deserialize, Serialize};
44+use text_range::TextRange;
55+use tree_sitter_graph::{
66+ ast::File, functions::Functions, ExecutionConfig, Identifier, NoCancellation, Variables,
77+};
88+99+mod debug;
1010+mod error;
1111+mod stdlib;
1212+1313+use error::{ConfigError, StagError};
1414+1515+#[derive(Default)]
1616+pub struct StagBuilder<'a> {
1717+ language: Option<tree_sitter::Language>,
1818+ stag_file: Option<&'a str>,
1919+ filename: Option<&'a str>,
2020+ source: Option<&'a str>,
2121+}
2222+2323+impl<'a> StagBuilder<'a> {
2424+ pub fn with_language(&mut self, language: tree_sitter::Language) -> &mut Self {
2525+ self.language = Some(language);
2626+ self
2727+ }
2828+2929+ pub fn with_stag_file(&mut self, stag_file: &'a str) -> &mut Self {
3030+ self.stag_file = Some(stag_file);
3131+ self
3232+ }
3333+3434+ pub fn with_source(&mut self, source: &'a str) -> &mut Self {
3535+ self.source = Some(source);
3636+ self
3737+ }
3838+3939+ pub fn with_file_name(&mut self, filename: &'a str) -> &mut Self {
4040+ self.filename = Some(filename);
4141+ self
4242+ }
4343+4444+ pub fn execute(&self) -> Result<ScopeGraph, StagError> {
4545+ let mut parser = tree_sitter::Parser::new();
4646+ let language = self.language.ok_or(ConfigError::MissingLanguage)?;
4747+ parser.set_language(language)?;
4848+4949+ let file = File::from_str(
5050+ language,
5151+ self.stag_file.ok_or(ConfigError::MissingStagSource)?,
5252+ )
5353+ .map_err(ConfigError::from)?;
5454+5555+ let mut functions = Functions::stdlib();
5656+ functions.add(Identifier::from("scope"), stdlib::ScopeShorthand);
5757+ functions.add(Identifier::from("def"), stdlib::DefShorthand);
5858+ functions.add(Identifier::from("ref"), stdlib::RefShortHand);
5959+ functions.add(Identifier::from("cover"), stdlib::CoverRanges);
6060+ functions.add(Identifier::from("range"), stdlib::NodeRange);
6161+ let globals = Variables::new();
6262+ let config = ExecutionConfig::new(&functions, &globals);
6363+6464+ let src = self.source.ok_or(ConfigError::MissingSource)?;
6565+ let tree = parser.parse(src.as_bytes(), None).unwrap();
6666+ let graph = file
6767+ .execute(&tree, &src, &config, &NoCancellation)
6868+ .map_err(ConfigError::from)?;
6969+7070+ let mut sg = ScopeGraph::new(tree.root_node().range().into());
7171+ sg = build_scope_graph(graph, sg);
7272+ Ok(sg)
7373+ }
7474+}
7575+7676+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
7777+pub struct LocalDef {
7878+ pub range: TextRange,
7979+ pub text: String,
8080+ pub symbol: Option<String>,
8181+}
8282+8383+impl LocalDef {
8484+ /// Initialize a new definition
8585+ pub fn new(range: TextRange, text: String, symbol: Option<String>) -> Self {
8686+ Self {
8787+ range,
8888+ text,
8989+ symbol,
9090+ }
9191+ }
9292+9393+ pub fn name<'a>(&self, buffer: &'a [u8]) -> &'a [u8] {
9494+ &buffer[self.range.start.byte..self.range.end.byte]
9595+ }
9696+}
9797+9898+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
9999+pub struct LocalImport {
100100+ pub range: TextRange,
101101+ pub text: String,
102102+}
103103+104104+impl LocalImport {
105105+ /// Initialize a new import
106106+ pub fn new(range: TextRange, text: String) -> Self {
107107+ Self { range, text }
108108+ }
109109+110110+ pub fn name<'a>(&self, buffer: &'a [u8]) -> &'a [u8] {
111111+ &buffer[self.range.start.byte..self.range.end.byte]
112112+ }
113113+}
114114+115115+#[derive(Debug, Clone, Serialize, Deserialize)]
116116+pub struct Reference {
117117+ pub range: TextRange,
118118+ pub text: String,
119119+ pub symbol: Option<String>,
120120+}
121121+122122+impl Reference {
123123+ /// Initialize a new reference
124124+ pub fn new(range: TextRange, text: String, symbol: Option<String>) -> Self {
125125+ Self {
126126+ range,
127127+ text,
128128+ symbol,
129129+ }
130130+ }
131131+}
132132+133133+#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
134134+pub struct LocalScope {
135135+ pub range: TextRange,
136136+}
137137+138138+impl LocalScope {
139139+ pub fn new(range: TextRange) -> Self {
140140+ Self { range }
141141+ }
142142+}
143143+144144+pub struct ScopeStack<'a> {
145145+ pub scope_graph: &'a ScopeGraph,
146146+ pub start: Option<NodeIndex<u32>>,
147147+}
148148+149149+impl<'a> Iterator for ScopeStack<'a> {
150150+ type Item = NodeIndex<u32>;
151151+ fn next(&mut self) -> Option<Self::Item> {
152152+ if let Some(start) = self.start {
153153+ let parent = self
154154+ .scope_graph
155155+ .graph
156156+ .edges_directed(start, Direction::Outgoing)
157157+ .find(|edge| *edge.weight() == EdgeKind::ScopeToScope)
158158+ .map(|edge| edge.target());
159159+ let original = start;
160160+ self.start = parent;
161161+ Some(original)
162162+ } else {
163163+ None
164164+ }
165165+ }
166166+}
167167+168168+/// The type of a node in the ScopeGraph
169169+#[derive(Serialize, Deserialize, Debug, Clone)]
170170+pub enum NodeKind {
171171+ /// A scope node
172172+ Scope(LocalScope),
173173+174174+ /// A definition node
175175+ Def(LocalDef),
176176+177177+ /// An import node
178178+ Import(LocalImport),
179179+180180+ /// A reference node
181181+ Ref(Reference),
182182+}
183183+184184+impl NodeKind {
185185+ /// Construct a scope node from a range
186186+ pub fn scope(range: TextRange) -> Self {
187187+ Self::Scope(LocalScope::new(range))
188188+ }
189189+190190+ /// Produce the range spanned by this node
191191+ pub fn range(&self) -> TextRange {
192192+ match self {
193193+ Self::Scope(l) => l.range,
194194+ Self::Def(d) => d.range,
195195+ Self::Ref(r) => r.range,
196196+ Self::Import(i) => i.range,
197197+ }
198198+ }
199199+}
200200+201201+/// Describes the relation between two nodes in the ScopeGraph
202202+#[derive(Serialize, Deserialize, PartialEq, Eq, Copy, Clone, Debug)]
203203+pub enum EdgeKind {
204204+ /// The edge weight from a nested scope to its parent scope
205205+ ScopeToScope,
206206+207207+ /// The edge weight from a definition to its definition scope
208208+ DefToScope,
209209+210210+ /// The edge weight from an import to its definition scope
211211+ ImportToScope,
212212+213213+ /// The edge weight from a reference to its definition
214214+ RefToDef,
215215+216216+ /// The edge weight from a reference to its import
217217+ RefToImport,
218218+}
219219+220220+/// A graph representation of scopes and names in a single syntax tree
221221+#[derive(Debug, Serialize, Deserialize, Clone)]
222222+pub struct ScopeGraph {
223223+ /// The raw graph
224224+ pub graph: Graph<NodeKind, EdgeKind>,
225225+226226+ // Graphs do not have the concept of a `root`, but lexical scopes follow the syntax
227227+ // tree, and as a result, have a "root" node. The root_idx points to a scope node that
228228+ // encompasses the entire file: the file-global scope.
229229+ root_idx: NodeIndex,
230230+}
231231+232232+impl ScopeGraph {
233233+ pub fn new(range: TextRange) -> Self {
234234+ let mut graph = Graph::new();
235235+ let root_idx = graph.add_node(NodeKind::scope(range));
236236+ Self { graph, root_idx }
237237+ }
238238+239239+ pub fn get_node(&self, node_idx: NodeIndex) -> Option<&NodeKind> {
240240+ self.graph.node_weight(node_idx)
241241+ }
242242+243243+ /// Insert a local scope into the scope-graph
244244+ fn insert_local_scope(&mut self, new: LocalScope) {
245245+ if let Some(parent_scope) = self.scope_by_range(new.range, self.root_idx) {
246246+ let new_scope = NodeKind::Scope(new);
247247+ let new_idx = self.graph.add_node(new_scope);
248248+ self.graph
249249+ .add_edge(new_idx, parent_scope, EdgeKind::ScopeToScope);
250250+ }
251251+ }
252252+253253+ /// Insert a def into the scope-graph
254254+ fn insert_local_def(&mut self, new: LocalDef) {
255255+ if let Some(defining_scope) = self.scope_by_range(new.range, self.root_idx) {
256256+ let new_def = NodeKind::Def(new);
257257+ let new_idx = self.graph.add_node(new_def);
258258+ self.graph
259259+ .add_edge(new_idx, defining_scope, EdgeKind::DefToScope);
260260+ }
261261+ }
262262+263263+ /// Insert a def into the scope-graph, at the root scope
264264+ #[allow(unused)]
265265+ fn insert_global_def(&mut self, new: LocalDef) {
266266+ let new_def = NodeKind::Def(new);
267267+ let new_idx = self.graph.add_node(new_def);
268268+ self.graph
269269+ .add_edge(new_idx, self.root_idx, EdgeKind::DefToScope);
270270+ }
271271+272272+ /// Insert an import into the scope-graph
273273+ fn insert_local_import(&mut self, new: LocalImport) {
274274+ if let Some(defining_scope) = self.scope_by_range(new.range, self.root_idx) {
275275+ let new_imp = NodeKind::Import(new);
276276+ let new_idx = self.graph.add_node(new_imp);
277277+ self.graph
278278+ .add_edge(new_idx, defining_scope, EdgeKind::ImportToScope);
279279+ }
280280+ }
281281+282282+ /// Insert a ref into the scope-graph
283283+ fn insert_ref(&mut self, new: Reference) {
284284+ let mut possible_defs = vec![];
285285+ let mut possible_imports = vec![];
286286+ if let Some(local_scope_idx) = self.scope_by_range(new.range, self.root_idx) {
287287+ // traverse the scopes from the current-scope to the root-scope
288288+ for scope in self.scope_stack(local_scope_idx) {
289289+ // find candidate definitions in each scope
290290+ for local_def in self
291291+ .graph
292292+ .edges_directed(scope, Direction::Incoming)
293293+ .filter(|edge| *edge.weight() == EdgeKind::DefToScope)
294294+ .map(|edge| edge.source())
295295+ {
296296+ if let NodeKind::Def(def) = &self.graph[local_def] {
297297+ if new.text == def.text {
298298+ match (def.symbol.as_ref(), new.symbol.as_ref()) {
299299+ // both contain symbols, but they don't belong to the same namepspace
300300+ (Some(d), Some(r)) if d != r => {}
301301+302302+ // in all other cases, form an edge from the ref to def.
303303+ // an empty symbol belongs to all namespaces:
304304+ // * (None, None)
305305+ // * (None, Some(_))
306306+ // * (Some(_), None)
307307+ // * (Some(_), Some(_)) if def.namespace == ref.namespace
308308+ _ => {
309309+ possible_defs.push(local_def);
310310+ }
311311+ };
312312+ }
313313+ }
314314+ }
315315+316316+ // find candidate imports in each scope
317317+ for local_import in self
318318+ .graph
319319+ .edges_directed(scope, Direction::Incoming)
320320+ .filter(|edge| *edge.weight() == EdgeKind::ImportToScope)
321321+ .map(|edge| edge.source())
322322+ {
323323+ if let NodeKind::Import(import) = &self.graph[local_import] {
324324+ if new.text == import.text {
325325+ possible_imports.push(local_import);
326326+ }
327327+ }
328328+ }
329329+ }
330330+ }
331331+332332+ if !possible_defs.is_empty() || !possible_imports.is_empty() {
333333+ let new_ref = NodeKind::Ref(new);
334334+ let ref_idx = self.graph.add_node(new_ref);
335335+ for def_idx in possible_defs {
336336+ self.graph.add_edge(ref_idx, def_idx, EdgeKind::RefToDef);
337337+ }
338338+ for imp_idx in possible_imports {
339339+ self.graph.add_edge(ref_idx, imp_idx, EdgeKind::RefToImport);
340340+ }
341341+ }
342342+ }
343343+344344+ fn scope_stack(&self, start: NodeIndex) -> ScopeStack<'_> {
345345+ ScopeStack {
346346+ scope_graph: self,
347347+ start: Some(start),
348348+ }
349349+ }
350350+351351+ // The smallest scope that encompasses `range`. Start at `start` and narrow down if possible.
352352+ fn scope_by_range(&self, range: TextRange, start: NodeIndex) -> Option<NodeIndex> {
353353+ let target_range = self.graph[start].range();
354354+ if target_range.contains(&range) {
355355+ let mut child_scopes = self
356356+ .graph
357357+ .edges_directed(start, Direction::Incoming)
358358+ .filter(|edge| *edge.weight() == EdgeKind::ScopeToScope)
359359+ .map(|edge| edge.source())
360360+ .collect::<Vec<_>>();
361361+362362+ child_scopes.sort_by_key(|s| self.graph[*s].range());
363363+ let target_child_scope = child_scopes.binary_search_by(|x| {
364364+ if self.graph[*x].range().contains(&range) {
365365+ std::cmp::Ordering::Equal
366366+ } else {
367367+ self.graph[*x].range().cmp(&range)
368368+ }
369369+ });
370370+371371+ if let Some(t) = target_child_scope
372372+ .ok()
373373+ .and_then(|idx| child_scopes.get(idx))
374374+ .and_then(|s| self.scope_by_range(range, *s))
375375+ {
376376+ return Some(t);
377377+ } else {
378378+ return Some(start);
379379+ }
380380+ }
381381+ None
382382+ }
383383+384384+ /// Produce a list of interesting ranges: ranges of defs and refs
385385+ pub fn hoverable_ranges(&self) -> Box<dyn Iterator<Item = TextRange> + '_> {
386386+ let iterator =
387387+ self.graph
388388+ .node_indices()
389389+ .filter_map(|node_idx| match &self.graph[node_idx] {
390390+ NodeKind::Scope(_) => None,
391391+ NodeKind::Def(d) => Some(d.range),
392392+ NodeKind::Ref(r) => Some(r.range),
393393+ NodeKind::Import(i) => Some(i.range),
394394+ });
395395+ Box::new(iterator)
396396+ }
397397+398398+ /// Produce possible definitions for a reference
399399+ pub fn definitions(
400400+ &self,
401401+ reference_node: NodeIndex,
402402+ ) -> Box<dyn Iterator<Item = NodeIndex> + '_> {
403403+ let iterator = self
404404+ .graph
405405+ .edges_directed(reference_node, Direction::Outgoing)
406406+ .filter(|edge| *edge.weight() == EdgeKind::RefToDef)
407407+ .map(|edge| edge.target());
408408+ Box::new(iterator)
409409+ }
410410+411411+ /// Produce possible imports for a reference
412412+ pub fn imports(&self, reference_node: NodeIndex) -> Box<dyn Iterator<Item = NodeIndex> + '_> {
413413+ let iterator = self
414414+ .graph
415415+ .edges_directed(reference_node, Direction::Outgoing)
416416+ .filter(|edge| *edge.weight() == EdgeKind::RefToImport)
417417+ .map(|edge| edge.target());
418418+ Box::new(iterator)
419419+ }
420420+421421+ /// Produce possible references for a definition/import node
422422+ pub fn references(
423423+ &self,
424424+ definition_node: NodeIndex,
425425+ ) -> Box<dyn Iterator<Item = NodeIndex> + '_> {
426426+ let iterator = self
427427+ .graph
428428+ .edges_directed(definition_node, Direction::Incoming)
429429+ .filter(|edge| {
430430+ *edge.weight() == EdgeKind::RefToDef || *edge.weight() == EdgeKind::RefToImport
431431+ })
432432+ .map(|edge| edge.source());
433433+ Box::new(iterator)
434434+ }
435435+436436+ pub fn node_by_range(&self, start_byte: usize, end_byte: usize) -> Option<NodeIndex> {
437437+ self.graph
438438+ .node_indices()
439439+ .filter(|&idx| self.is_definition(idx) || self.is_reference(idx) || self.is_import(idx))
440440+ .find(|&idx| {
441441+ let node = self.graph[idx].range();
442442+ start_byte >= node.start.byte && end_byte <= node.end.byte
443443+ })
444444+ }
445445+446446+ pub fn node_by_position(&self, line: usize, column: usize) -> Option<NodeIndex> {
447447+ self.graph
448448+ .node_indices()
449449+ .filter(|&idx| self.is_definition(idx) || self.is_reference(idx))
450450+ .find(|&idx| {
451451+ let node = self.graph[idx].range();
452452+ node.start.line == line
453453+ && node.end.line == line
454454+ && node.start.column <= column
455455+ && node.end.column >= column
456456+ })
457457+ }
458458+459459+ #[cfg(test)]
460460+ pub fn find_node_by_name(&self, src: &[u8], name: &[u8]) -> Option<NodeIndex> {
461461+ self.graph.node_indices().find(|idx| {
462462+ matches!(
463463+ &self.graph[*idx],
464464+ NodeKind::Def(d) if d.name(src) == name)
465465+ })
466466+ }
467467+468468+ #[cfg(test)]
469469+ pub fn debug(&self, src: &[u8]) -> debug::ScopeDebug {
470470+ let graph = &self.graph;
471471+ let start = self.root_idx;
472472+ debug::ScopeDebug::new(graph, start, src)
473473+ }
474474+475475+ pub fn is_definition(&self, node_idx: NodeIndex) -> bool {
476476+ matches!(self.graph[node_idx], NodeKind::Def(_))
477477+ }
478478+479479+ pub fn is_reference(&self, node_idx: NodeIndex) -> bool {
480480+ matches!(self.graph[node_idx], NodeKind::Ref(_))
481481+ }
482482+483483+ pub fn is_scope(&self, node_idx: NodeIndex) -> bool {
484484+ matches!(self.graph[node_idx], NodeKind::Scope(_))
485485+ }
486486+487487+ pub fn is_import(&self, node_idx: NodeIndex) -> bool {
488488+ matches!(self.graph[node_idx], NodeKind::Import(_))
489489+ }
490490+}
491491+492492+fn build_scope_graph(
493493+ tsg: tree_sitter_graph::graph::Graph,
494494+ mut scope_graph: ScopeGraph,
495495+) -> ScopeGraph {
496496+ let nodes = tsg.iter_nodes().collect::<Vec<_>>();
497497+ for node in nodes
498498+ .iter()
499499+ .map(|node_ref| &tsg[*node_ref])
500500+ .filter(|node| is_scope(node))
501501+ {
502502+ let range =
503503+ text_range::value_to_range(node.attributes.get(&Identifier::from("range")).unwrap());
504504+ let scope = LocalScope::new(range.into());
505505+ scope_graph.insert_local_scope(scope);
506506+ }
507507+508508+ for node in nodes
509509+ .iter()
510510+ .map(|node_ref| &tsg[*node_ref])
511511+ .filter(|node| is_import(node))
512512+ {
513513+ let range =
514514+ text_range::value_to_range(node.attributes.get(&Identifier::from("range")).unwrap());
515515+ let text = node
516516+ .attributes
517517+ .get(&Identifier::from("text"))
518518+ .and_then(|id| id.clone().into_string().ok())
519519+ .expect("import without text");
520520+ let import = LocalImport::new(range.into(), text);
521521+ scope_graph.insert_local_import(import);
522522+ }
523523+524524+ for node in nodes
525525+ .iter()
526526+ .map(|node_ref| &tsg[*node_ref])
527527+ .filter(|node| is_def(node))
528528+ {
529529+ let range =
530530+ text_range::value_to_range(node.attributes.get(&Identifier::from("range")).unwrap());
531531+ let symbol = node
532532+ .attributes
533533+ .get(&Identifier::from("symbol"))
534534+ .and_then(|id| id.clone().into_string().ok());
535535+ let text = node
536536+ .attributes
537537+ .get(&Identifier::from("text"))
538538+ .and_then(|id| id.clone().into_string().ok())
539539+ .expect("def without text");
540540+ let local_def = LocalDef::new(range.into(), text, symbol);
541541+542542+ // TODO: fix scoping here
543543+ scope_graph.insert_local_def(local_def);
544544+ }
545545+546546+ for node in nodes
547547+ .iter()
548548+ .map(|node_ref| &tsg[*node_ref])
549549+ .filter(|node| is_ref(node))
550550+ {
551551+ let range =
552552+ text_range::value_to_range(node.attributes.get(&Identifier::from("range")).unwrap());
553553+ let symbol = node
554554+ .attributes
555555+ .get(&Identifier::from("symbol"))
556556+ .and_then(|id| id.clone().into_string().ok());
557557+ let text = node
558558+ .attributes
559559+ .get(&Identifier::from("text"))
560560+ .and_then(|id| id.clone().into_string().ok())
561561+ .expect("ref without text");
562562+ let ref_ = Reference::new(range.into(), text, symbol);
563563+564564+ scope_graph.insert_ref(ref_);
565565+ }
566566+567567+ scope_graph
568568+}
569569+570570+fn is_string_attr(node: &tree_sitter_graph::graph::GraphNode, key: &str, value: &str) -> bool {
571571+ matches!(node.attributes.get(&Identifier::from(key)).and_then(|v| v.as_str().ok()), Some(v) if v == value)
572572+}
573573+574574+fn is_scope(node: &tree_sitter_graph::graph::GraphNode) -> bool {
575575+ is_string_attr(node, "kind", "scope")
576576+}
577577+578578+fn is_import(node: &tree_sitter_graph::graph::GraphNode) -> bool {
579579+ is_string_attr(node, "kind", "import")
580580+}
581581+582582+fn is_def(node: &tree_sitter_graph::graph::GraphNode) -> bool {
583583+ is_string_attr(node, "kind", "def")
584584+}
585585+586586+fn is_ref(node: &tree_sitter_graph::graph::GraphNode) -> bool {
587587+ is_string_attr(node, "kind", "ref")
588588+}
589589+590590+#[cfg(test)]
591591+mod tests {
592592+ use super::*;
593593+ use expect_test::{expect, Expect};
594594+595595+ fn counts(src: &str) -> (usize, usize, usize, usize) {
596596+ let sg = build_graph(src);
597597+ let nodes = sg.graph.node_weights();
598598+599599+ nodes.fold((0, 0, 0, 0), |(s, d, r, i), node| match node {
600600+ NodeKind::Scope(_) => (s + 1, d, r, i),
601601+ NodeKind::Def(_) => (s, d + 1, r, i),
602602+ NodeKind::Ref(_) => (s, d, r + 1, i),
603603+ NodeKind::Import(_) => (s, d, r, i + 1),
604604+ })
605605+ }
606606+607607+ pub fn test_scopes(src: &str, expected: Expect) {
608608+ let graph = build_graph(src);
609609+ let observed = graph.debug(src.as_bytes());
610610+ expected.assert_debug_eq(&observed)
611611+ }
612612+613613+ pub fn build_graph(src: &str) -> ScopeGraph {
614614+ StagBuilder::default()
615615+ .with_source(src)
616616+ .with_stag_file(include_str!("stag.tsg"))
617617+ .with_language(tree_sitter_rust::language())
618618+ .execute()
619619+ .unwrap()
620620+ }
621621+622622+ #[test]
623623+ fn declare_const_and_static() {
624624+ let src = r#"
625625+ const a: () = ();
626626+ static b: () = ();
627627+ "#;
628628+629629+ let (_, def_count, _, _) = counts(src);
630630+631631+ // a, b
632632+ assert_eq!(def_count, 2);
633633+ }
634634+635635+ #[test]
636636+ fn declare_let_statement() {
637637+ let src = r#"
638638+ fn main() {
639639+ let a = ();
640640+ let (b, c) = ();
641641+ let S { d, e } = ();
642642+ let S { field: f, g } = ();
643643+ let S { h, .. } = ();
644644+ let S { i, field: _ } = ();
645645+ }
646646+ "#;
647647+ let (_, def_count, _, _) = counts(src);
648648+649649+ // main, a, b, c, d, e, f, g, h, i
650650+ assert_eq!(def_count, 10);
651651+ }
652652+653653+ #[test]
654654+ fn declare_function_params() {
655655+ let src = r#"
656656+ fn f1(a: T) {}
657657+ fn f2(b: T, c: T) {}
658658+ fn f3((d, e): (T, U)) {}
659659+ fn f4(S {f, g}: S) {}
660660+ fn f5(S {h, ..}: S) {}
661661+ fn f6(S { field: i }: S) {}
662662+ "#;
663663+ let (_, def_count, _, _) = counts(src);
664664+665665+ // f1, f2, f3, f4, f5, f6, a, b, c, d, e, f, g, h, i
666666+ assert_eq!(def_count, 15);
667667+ }
668668+669669+ #[test]
670670+ fn declare_closure_params() {
671671+ let src = r#"
672672+ fn main() {
673673+ let _ = |x| {};
674674+ let _ = |x, y| {};
675675+ let _ = |x: ()| {};
676676+ let _ = |(x, y): ()| {};
677677+ }
678678+ "#;
679679+ let (_, def_count, _, _) = counts(src);
680680+681681+ // main,
682682+ // x,
683683+ // x, y,
684684+ // x,
685685+ // x, y
686686+ assert_eq!(def_count, 7);
687687+ }
688688+689689+ #[test]
690690+ fn declare_labels() {
691691+ let src = r#"
692692+ fn main() {
693693+ 'loop: loop {};
694694+ 'loop: for _ in () {}
695695+ 'loop: while true {}
696696+ }
697697+ "#;
698698+ let (_, def_count, _, _) = counts(src);
699699+700700+ // main, 'loop x3
701701+ assert_eq!(def_count, 4);
702702+ }
703703+704704+ #[test]
705705+ fn declare_types() {
706706+ let src = r#"
707707+ struct One {
708708+ two: T,
709709+ three: T,
710710+ }
711711+712712+ enum Four {
713713+ Five,
714714+ Six(T),
715715+ Seven {
716716+ eight: T
717717+ }
718718+ }
719719+720720+ union Nine {}
721721+722722+ type Ten = ();
723723+ "#;
724724+ let (_, def_count, _, _) = counts(src);
725725+726726+ assert_eq!(def_count, 10);
727727+ }
728728+729729+ #[test]
730730+ fn declare_namespaces() {
731731+ let src = r#"
732732+ mod one {}
733733+ pub mod two {}
734734+ mod three {
735735+ mod four {}
736736+ }
737737+ "#;
738738+ let (_, def_count, _, _) = counts(src);
739739+740740+ assert_eq!(def_count, 4);
741741+ }
742742+743743+ #[test]
744744+ fn declare_let_expr() {
745745+ let src = r#"
746746+ if let a = () {}
747747+ if let Some(a) = () {}
748748+749749+ while let a = () {}
750750+ while let Some(a) = () {}
751751+ "#;
752752+ let (_, def_count, _, _) = counts(src);
753753+754754+ assert_eq!(def_count, 4);
755755+ }
756756+757757+ #[test]
758758+ fn refer_unary_expr() {
759759+ let src = r#"
760760+ fn main() {
761761+ let a = 2;
762762+ !a;
763763+ -a;
764764+ *a;
765765+ }
766766+ "#;
767767+ let (_, _, ref_count, _) = counts(src);
768768+769769+ assert_eq!(ref_count, 3);
770770+ }
771771+772772+ #[test]
773773+ fn refer_binary_expr() {
774774+ let src = r#"
775775+ fn main() {
776776+ let a = 2;
777777+ let b = 3;
778778+ a + b;
779779+ a >> b;
780780+ }
781781+ "#;
782782+ let (_, _, ref_count, _) = counts(src);
783783+784784+ assert_eq!(ref_count, 4);
785785+ }
786786+787787+ #[test]
788788+ fn refer_control_flow() {
789789+ let src = r#"
790790+ fn main() {
791791+ let a = 2;
792792+793793+ // 1
794794+ if a {}
795795+796796+ // 2
797797+ if _ {} else if a {}
798798+799799+ // 3
800800+ while a {
801801+ // 4
802802+ break a;
803803+ }
804804+805805+ // 5
806806+ a?;
807807+808808+ // 6
809809+ return a;
810810+811811+ // 7
812812+ a.await;
813813+814814+ // 8
815815+ yield a;
816816+ }
817817+ "#;
818818+ let (_, _, ref_count, _) = counts(src);
819819+820820+ assert_eq!(ref_count, 8);
821821+ }
822822+823823+ #[test]
824824+ fn refer_assignment() {
825825+ let src = r#"
826826+ fn main() {
827827+ let mut a = 2;
828828+ a += 2;
829829+ a = 2;
830830+ a *= 2;
831831+ }
832832+ "#;
833833+ let (_, _, ref_count, _) = counts(src);
834834+835835+ assert_eq!(ref_count, 3);
836836+ }
837837+838838+ #[test]
839839+ fn refer_struct_expr() {
840840+ let src = r#"
841841+ fn main() {
842842+ let a = 2;
843843+ let b = 2;
844844+ S { a, b };
845845+ S { ..a };
846846+ S { field: a, b };
847847+ }
848848+ "#;
849849+ let (_, _, ref_count, _) = counts(src);
850850+851851+ assert_eq!(ref_count, 5);
852852+ }
853853+854854+ #[test]
855855+ fn refer_dot() {
856856+ let src = r#"
857857+ fn main() {
858858+ let a = S {};
859859+860860+ a.b;
861861+ a.foo();
862862+ }
863863+ "#;
864864+ let (_, _, ref_count, _) = counts(src);
865865+866866+ assert_eq!(ref_count, 2);
867867+ }
868868+869869+ #[test]
870870+ fn refer_arguments() {
871871+ let src = r#"
872872+ fn main() {
873873+ let a = 2;
874874+ let b = 3;
875875+ foo(a, b);
876876+ }
877877+ "#;
878878+ let (_, _, ref_count, _) = counts(src);
879879+880880+ assert_eq!(ref_count, 2);
881881+ }
882882+883883+ #[test]
884884+ fn function_params() {
885885+ test_scopes(
886886+ r#"
887887+ fn foo(t: T, u: U) -> R {}
888888+ "#,
889889+ expect![[r#"
890890+ scope {
891891+ definitions: [
892892+ foo {
893893+ context: "fn §foo§(t: T, u: U) -> R {}",
894894+ },
895895+ ],
896896+ child scopes: [
897897+ scope {
898898+ definitions: [
899899+ t {
900900+ context: "fn foo(§t§: T, u: U) -> R {}",
901901+ },
902902+ u {
903903+ context: "fn foo(t: T, §u§: U) -> R {}",
904904+ },
905905+ ],
906906+ child scopes: [],
907907+ },
908908+ scope {
909909+ definitions: [],
910910+ child scopes: [],
911911+ },
912912+ ],
913913+ }
914914+ "#]],
915915+ );
916916+ }
917917+918918+ #[test]
919919+ fn use_statements() {
920920+ test_scopes(
921921+ r#"
922922+ mod intelligence;
923923+924924+ use bleep;
925925+ use super::test_utils;
926926+ use intelligence::language as lang;
927927+ use crate::text_range::{TextRange, Point};
928928+ "#,
929929+ expect![[r#"
930930+ scope {
931931+ definitions: [
932932+ intelligence {
933933+ context: "mod §intelligence§;",
934934+ referenced in (1): [
935935+ `use §intelligence§::language as lang;`,
936936+ ],
937937+ },
938938+ bleep {
939939+ context: "use §bleep§;",
940940+ },
941941+ test_utils {
942942+ context: "use super::§test_utils§;",
943943+ },
944944+ lang {
945945+ context: "use intelligence::language as §lang§;",
946946+ },
947947+ TextRange {
948948+ context: "use crate::text_range::{§TextRange§, Point};",
949949+ },
950950+ Point {
951951+ context: "use crate::text_range::{TextRange, §Point§};",
952952+ },
953953+ ],
954954+ child scopes: [],
955955+ }
956956+ "#]],
957957+ )
958958+ }
959959+960960+ #[test]
961961+ fn lifetimes() {
962962+ test_scopes(
963963+ r#"
964964+ impl<'a, T> Trait for Struct<'a, T> {
965965+ fn foo<'b>(&'a self) -> &'b T { }
966966+ }
967967+ "#,
968968+ expect![[r#"
969969+ scope {
970970+ definitions: [],
971971+ child scopes: [
972972+ scope {
973973+ definitions: [
974974+ 'a {
975975+ context: "impl<§'a§, T> Trait for Struct<'a, T> {",
976976+ referenced in (2): [
977977+ `impl<'a, T> Trait for Struct<§'a§, T> {`,
978978+ `fn foo<'b>(&§'a§ self) -> &'b T { }`,
979979+ ],
980980+ },
981981+ T {
982982+ context: "impl<'a, §T§> Trait for Struct<'a, T> {",
983983+ referenced in (2): [
984984+ `impl<'a, T> Trait for Struct<'a, §T§> {`,
985985+ `fn foo<'b>(&'a self) -> &'b §T§ { }`,
986986+ ],
987987+ },
988988+ ],
989989+ child scopes: [
990990+ scope {
991991+ definitions: [
992992+ foo {
993993+ context: "fn §foo§<'b>(&'a self) -> &'b T { }",
994994+ },
995995+ 'b {
996996+ context: "fn foo<§'b§>(&'a self) -> &'b T { }",
997997+ referenced in (1): [
998998+ `fn foo<'b>(&'a self) -> &§'b§ T { }`,
999999+ ],
10001000+ },
10011001+ ],
10021002+ child scopes: [
10031003+ scope {
10041004+ definitions: [
10051005+ self {
10061006+ context: "fn foo<'b>(&'a §self§) -> &'b T { }",
10071007+ },
10081008+ ],
10091009+ child scopes: [],
10101010+ },
10111011+ scope {
10121012+ definitions: [],
10131013+ child scopes: [],
10141014+ },
10151015+ ],
10161016+ },
10171017+ ],
10181018+ },
10191019+ ],
10201020+ }
10211021+ "#]],
10221022+ )
10231023+ }
10241024+10251025+ #[test]
10261026+ fn generics_and_traits() {
10271027+ test_scopes(
10281028+ r#"
10291029+ trait Foo {}
10301030+10311031+ fn foo<'a, 'b, T, U: Foo<T> + 'a>(t: T, u: U)
10321032+ where T: Foo + 'b,
10331033+ { }
10341034+ "#,
10351035+ expect![[r#"
10361036+ scope {
10371037+ definitions: [
10381038+ Foo {
10391039+ context: "trait §Foo§ {}",
10401040+ referenced in (2): [
10411041+ `fn foo<'a, 'b, T, U: §Foo§<T> + 'a>(t: T, u: U)`,
10421042+ `where T: §Foo§ + 'b,`,
10431043+ ],
10441044+ },
10451045+ foo {
10461046+ context: "fn §foo§<'a, 'b, T, U: Foo<T> + 'a>(t: T, u: U)",
10471047+ },
10481048+ 'a {
10491049+ context: "fn foo<§'a§, 'b, T, U: Foo<T> + 'a>(t: T, u: U)",
10501050+ referenced in (1): [
10511051+ `fn foo<'a, 'b, T, U: Foo<T> + §'a§>(t: T, u: U)`,
10521052+ ],
10531053+ },
10541054+ 'b {
10551055+ context: "fn foo<'a, §'b§, T, U: Foo<T> + 'a>(t: T, u: U)",
10561056+ referenced in (1): [
10571057+ `where T: Foo + §'b§,`,
10581058+ ],
10591059+ },
10601060+ T {
10611061+ context: "fn foo<'a, 'b, §T§, U: Foo<T> + 'a>(t: T, u: U)",
10621062+ referenced in (3): [
10631063+ `fn foo<'a, 'b, T, U: Foo<§T§> + 'a>(t: T, u: U)`,
10641064+ `fn foo<'a, 'b, T, U: Foo<T> + 'a>(t: §T§, u: U)`,
10651065+ `where §T§: Foo + 'b,`,
10661066+ ],
10671067+ },
10681068+ U {
10691069+ context: "fn foo<'a, 'b, T, §U§: Foo<T> + 'a>(t: T, u: U)",
10701070+ referenced in (1): [
10711071+ `fn foo<'a, 'b, T, U: Foo<T> + 'a>(t: T, u: §U§)`,
10721072+ ],
10731073+ },
10741074+ ],
10751075+ child scopes: [
10761076+ scope {
10771077+ definitions: [],
10781078+ child scopes: [
10791079+ scope {
10801080+ definitions: [],
10811081+ child scopes: [
10821082+ scope {
10831083+ definitions: [],
10841084+ child scopes: [],
10851085+ },
10861086+ ],
10871087+ },
10881088+ ],
10891089+ },
10901090+ scope {
10911091+ definitions: [
10921092+ t {
10931093+ context: "fn foo<'a, 'b, T, U: Foo<T> + 'a>(§t§: T, u: U)",
10941094+ },
10951095+ u {
10961096+ context: "fn foo<'a, 'b, T, U: Foo<T> + 'a>(t: T, §u§: U)",
10971097+ },
10981098+ ],
10991099+ child scopes: [],
11001100+ },
11011101+ scope {
11021102+ definitions: [],
11031103+ child scopes: [],
11041104+ },
11051105+ ],
11061106+ }
11071107+ "#]],
11081108+ )
11091109+ }
11101110+11111111+ #[test]
11121112+ fn type_constructors() {
11131113+ test_scopes(
11141114+ r#"
11151115+ struct Highlight {}
11161116+11171117+ enum Direction { Incoming, Outgoing }
11181118+11191119+ fn foo() -> Highlight {
11201120+ Highlight { }
11211121+ }
11221122+11231123+ fn bar() -> Direction {
11241124+ Direction::Incoming
11251125+ }
11261126+ "#,
11271127+ expect![[r#"
11281128+ scope {
11291129+ definitions: [
11301130+ Highlight {
11311131+ context: "struct §Highlight§ {}",
11321132+ referenced in (2): [
11331133+ `fn foo() -> §Highlight§ {`,
11341134+ `§Highlight§ { }`,
11351135+ ],
11361136+ },
11371137+ Direction {
11381138+ context: "enum §Direction§ { Incoming, Outgoing }",
11391139+ referenced in (2): [
11401140+ `fn bar() -> §Direction§ {`,
11411141+ `§Direction§::Incoming`,
11421142+ ],
11431143+ },
11441144+ foo {
11451145+ context: "fn §foo§() -> Highlight {",
11461146+ },
11471147+ bar {
11481148+ context: "fn §bar§() -> Direction {",
11491149+ },
11501150+ ],
11511151+ child scopes: [
11521152+ scope {
11531153+ definitions: [],
11541154+ child scopes: [
11551155+ scope {
11561156+ definitions: [],
11571157+ child scopes: [],
11581158+ },
11591159+ ],
11601160+ },
11611161+ scope {
11621162+ definitions: [],
11631163+ child scopes: [
11641164+ scope {
11651165+ definitions: [
11661166+ Incoming {
11671167+ context: "enum Direction { §Incoming§, Outgoing }",
11681168+ },
11691169+ Outgoing {
11701170+ context: "enum Direction { Incoming, §Outgoing§ }",
11711171+ },
11721172+ ],
11731173+ child scopes: [],
11741174+ },
11751175+ ],
11761176+ },
11771177+ scope {
11781178+ definitions: [],
11791179+ child scopes: [],
11801180+ },
11811181+ scope {
11821182+ definitions: [],
11831183+ child scopes: [],
11841184+ },
11851185+ scope {
11861186+ definitions: [],
11871187+ child scopes: [],
11881188+ },
11891189+ scope {
11901190+ definitions: [],
11911191+ child scopes: [],
11921192+ },
11931193+ ],
11941194+ }
11951195+ "#]],
11961196+ )
11971197+ }
11981198+11991199+ #[test]
12001200+ fn macros() {
12011201+ test_scopes(
12021202+ r#"
12031203+ fn main() {
12041204+ let (a, b, c) = ();
12051205+ // top-level tokens
12061206+ assert_eq!(a, b + c);
12071207+12081208+ // nested tokens
12091209+ println!("{}", if a { b } then { c });
12101210+ }
12111211+ "#,
12121212+ expect![[r#"
12131213+ scope {
12141214+ definitions: [
12151215+ main {
12161216+ context: "fn §main§() {",
12171217+ },
12181218+ ],
12191219+ child scopes: [
12201220+ scope {
12211221+ definitions: [],
12221222+ child scopes: [],
12231223+ },
12241224+ scope {
12251225+ definitions: [
12261226+ a {
12271227+ context: "let (§a§, b, c) = ();",
12281228+ referenced in (2): [
12291229+ `assert_eq!(§a§, b + c);`,
12301230+ `println!("{}", if §a§ { b } then { c });`,
12311231+ ],
12321232+ },
12331233+ b {
12341234+ context: "let (a, §b§, c) = ();",
12351235+ referenced in (2): [
12361236+ `assert_eq!(a, §b§ + c);`,
12371237+ `println!("{}", if a { §b§ } then { c });`,
12381238+ ],
12391239+ },
12401240+ c {
12411241+ context: "let (a, b, §c§) = ();",
12421242+ referenced in (2): [
12431243+ `assert_eq!(a, b + §c§);`,
12441244+ `println!("{}", if a { b } then { §c§ });`,
12451245+ ],
12461246+ },
12471247+ ],
12481248+ child scopes: [],
12491249+ },
12501250+ ],
12511251+ }
12521252+ "#]],
12531253+ )
12541254+ }
12551255+12561256+ // Self::method and self.method can be raised as references
12571257+ #[test]
12581258+ fn handle_self_type_and_var() {
12591259+ test_scopes(
12601260+ r#"
12611261+ struct MyStruct {}
12621262+12631263+ impl MyStruct {
12641264+ fn foo() {
12651265+ Self::foo()
12661266+ }
12671267+12681268+ fn bar(&self) {
12691269+ self.bar()
12701270+ }
12711271+ }
12721272+ "#,
12731273+ expect![[r#"
12741274+ scope {
12751275+ definitions: [
12761276+ MyStruct {
12771277+ context: "struct §MyStruct§ {}",
12781278+ referenced in (1): [
12791279+ `impl §MyStruct§ {`,
12801280+ ],
12811281+ },
12821282+ ],
12831283+ child scopes: [
12841284+ scope {
12851285+ definitions: [],
12861286+ child scopes: [
12871287+ scope {
12881288+ definitions: [],
12891289+ child scopes: [],
12901290+ },
12911291+ ],
12921292+ },
12931293+ scope {
12941294+ definitions: [],
12951295+ child scopes: [
12961296+ scope {
12971297+ definitions: [
12981298+ foo {
12991299+ context: "fn §foo§() {",
13001300+ referenced in (1): [
13011301+ `Self::§foo§()`,
13021302+ ],
13031303+ },
13041304+ bar {
13051305+ context: "fn §bar§(&self) {",
13061306+ referenced in (1): [
13071307+ `self.§bar§()`,
13081308+ ],
13091309+ },
13101310+ ],
13111311+ child scopes: [
13121312+ scope {
13131313+ definitions: [],
13141314+ child scopes: [],
13151315+ },
13161316+ scope {
13171317+ definitions: [],
13181318+ child scopes: [],
13191319+ },
13201320+ scope {
13211321+ definitions: [
13221322+ self {
13231323+ context: "fn bar(&§self§) {",
13241324+ },
13251325+ ],
13261326+ child scopes: [],
13271327+ },
13281328+ scope {
13291329+ definitions: [],
13301330+ child scopes: [],
13311331+ },
13321332+ ],
13331333+ },
13341334+ ],
13351335+ },
13361336+ ],
13371337+ }
13381338+ "#]],
13391339+ )
13401340+ }
13411341+13421342+ #[test]
13431343+ fn let_else_1_65_support() {
13441344+ test_scopes(
13451345+ r#"
13461346+ fn main() {
13471347+ let a = 3;
13481348+ if let b = a
13491349+ && let c = b
13501350+ && let d = c {
13511351+ d
13521352+ } else {
13531353+ return;
13541354+ }
13551355+ }
13561356+ "#,
13571357+ expect![[r#"
13581358+ scope {
13591359+ definitions: [
13601360+ main {
13611361+ context: "fn §main§() {",
13621362+ },
13631363+ ],
13641364+ child scopes: [
13651365+ scope {
13661366+ definitions: [],
13671367+ child scopes: [],
13681368+ },
13691369+ scope {
13701370+ definitions: [
13711371+ a {
13721372+ context: "let §a§ = 3;",
13731373+ referenced in (1): [
13741374+ `if let b = §a§`,
13751375+ ],
13761376+ },
13771377+ ],
13781378+ child scopes: [
13791379+ scope {
13801380+ definitions: [
13811381+ b {
13821382+ context: "if let §b§ = a",
13831383+ referenced in (1): [
13841384+ `&& let c = §b§`,
13851385+ ],
13861386+ },
13871387+ c {
13881388+ context: "&& let §c§ = b",
13891389+ referenced in (1): [
13901390+ `&& let d = §c§ {`,
13911391+ ],
13921392+ },
13931393+ d {
13941394+ context: "&& let §d§ = c {",
13951395+ },
13961396+ ],
13971397+ child scopes: [],
13981398+ },
13991399+ scope {
14001400+ definitions: [],
14011401+ child scopes: [],
14021402+ },
14031403+ scope {
14041404+ definitions: [],
14051405+ child scopes: [],
14061406+ },
14071407+ ],
14081408+ },
14091409+ ],
14101410+ }
14111411+ "#]],
14121412+ )
14131413+ }
14141414+}
+30
src/main.rs
···11+use stag::StagBuilder;
22+33+fn main() {
44+ let scopes = std::fs::read_to_string("src/stag.tsg").unwrap();
55+ let src = r#"
66+ fn main() {
77+ let x = 2;
88+ let a = 5;
99+ if let _ = z {
1010+ a[x];
1111+ }
1212+ }
1313+ "#;
1414+1515+ let sg = StagBuilder::default()
1616+ .with_source(src)
1717+ .with_stag_file(&scopes)
1818+ .with_language(tree_sitter_rust::language())
1919+ .execute()
2020+ .unwrap();
2121+2222+ for edge in sg.graph.raw_edges() {
2323+ let s = edge.source();
2424+ let t = edge.target();
2525+ let sn = &sg.graph[s];
2626+ let st = &sg.graph[t];
2727+ println!("{:?} -> {:?}", edge.source(), edge.target());
2828+ println!("{:#?} -> {:#?}", sn, st);
2929+ }
3030+}
+463
src/scopes.scm
···11+;; see tree-sitter-rust/src/grammar.json for an exhaustive list of productions
22+33+;; scopes
44+(block) @local.scope ; { ... }
55+(function_item) @local.scope
66+(declaration_list) @local.scope ; mod { ... }
77+88+;; impl items can define types and lifetimes:
99+;;
1010+;; impl<'a, T> Trait for Struct { .. }
1111+;;
1212+;; in order to constrain those to the impl block,
1313+;; we add a local scope here:
1414+(impl_item) @local.scope
1515+(struct_item) @local.scope
1616+(enum_item) @local.scope
1717+(union_item) @local.scope
1818+(type_item) @local.scope
1919+(trait_item) @local.scope
2020+2121+;; let expressions create scopes
2222+(if_expression
2323+ [(let_condition)
2424+ (let_chain)]) @local.scope
2525+2626+;; each match arm can bind variables with
2727+;; patterns, without creating a block scope;
2828+;;
2929+;; match _ {
3030+;; (a, b) => a,
3131+;; }
3232+;;
3333+;; The bindings for a, b are constrained to
3434+;; the match arm.
3535+(match_arm) @local.scope
3636+3737+;; loop labels are defs that are available only
3838+;; within the scope they create:
3939+;;
4040+;; 'outer: loop {
4141+;; let x = 2;
4242+;; };
4343+;; let y = 2;
4444+;;
4545+;; Produces a scope graph like so:
4646+;;
4747+;; {
4848+;; defs: [ y ],
4949+;; scopes: [
5050+;; {
5151+;; defs: [ 'outer ],
5252+;; scopes: [
5353+;; {
5454+;; defs: [ x ]
5555+;; }
5656+;; ]
5757+;; }
5858+;; ]
5959+;; }
6060+;;
6161+(loop_expression) @local.scope
6262+(for_expression) @local.scope
6363+(while_expression) @local.scope
6464+6565+6666+;; defs
6767+6868+;; let x = ...;
6969+(let_declaration
7070+ pattern: (identifier) @local.definition.variable)
7171+7272+;; if let x = ...;
7373+;; while let x = ...;
7474+(let_condition
7575+ .
7676+ (identifier) @local.definition.variable)
7777+7878+;; let (a, b, ...) = ..;
7979+;; if let (a, b, ...) = {}
8080+;; while let (a, b, ...) = {}
8181+;; match _ { (a, b) => { .. } }
8282+(tuple_pattern (identifier) @local.definition.variable)
8383+8484+;; Some(a)
8585+(tuple_struct_pattern
8686+ type: (_)
8787+ (identifier) @local.definition.variable)
8888+8989+;; let S { field: a } = ..;
9090+(struct_pattern
9191+ (field_pattern
9292+ (identifier) @local.definition.variable))
9393+9494+;; let S { a, b } = ..;
9595+(struct_pattern
9696+ (field_pattern
9797+ (shorthand_field_identifier) @local.definition.variable))
9898+9999+;; (mut x: T)
100100+(mut_pattern (identifier) @local.definition.variable)
101101+102102+;; (ref x: T)
103103+(ref_pattern (identifier) @local.definition.variable)
104104+105105+;; const x = ...;
106106+(const_item (identifier) @local.definition.const)
107107+108108+;; static x = ...;
109109+(static_item (identifier) @local.definition.const)
110110+111111+;; fn _(x: _)
112112+(parameters
113113+ (parameter
114114+ pattern: (identifier) @local.definition.variable))
115115+;; fn _(self)
116116+(parameters
117117+ (self_parameter
118118+ (self) @local.definition.variable))
119119+120120+;; type parameters
121121+(type_parameters
122122+ (type_identifier) @local.definition.typedef)
123123+(type_parameters
124124+ (lifetime) @local.definition.lifetime)
125125+(constrained_type_parameter
126126+ left: (type_identifier) @local.definition.typedef)
127127+128128+;; |x| { ... }
129129+;; no type
130130+(closure_parameters (identifier) @local.definition.variable)
131131+132132+;; |x: T| { ... }
133133+;; with type
134134+(closure_parameters
135135+ (parameter
136136+ (identifier) @local.definition.variable))
137137+138138+;;fn x(..)
139139+(function_item (identifier) @hoist.definition.function)
140140+141141+;; 'outer: loop { .. }
142142+(loop_expression
143143+ (loop_label) @local.definition.label)
144144+145145+;; `for` exprs create two defs: a label (if any) and the
146146+;; loop variable
147147+(for_expression . (identifier) @local.definition.variable)
148148+(for_expression (loop_label) @local.definition.label)
149149+150150+;; 'label: while cond { .. }
151151+(while_expression
152152+ (loop_label) @local.definition.label)
153153+154154+;; type definitions
155155+(struct_item (type_identifier) @hoist.definition.struct)
156156+(enum_item (type_identifier) @hoist.definition.enum)
157157+(union_item (type_identifier) @hoist.definition.union)
158158+(type_item . (type_identifier) @hoist.definition.typedef)
159159+(trait_item (type_identifier) @hoist.definition.interface)
160160+161161+;; struct and union fields
162162+(field_declaration_list
163163+ (field_declaration
164164+ (field_identifier) @local.definition.field))
165165+166166+;; enum variants
167167+(enum_variant_list
168168+ (enum_variant
169169+ (identifier) @local.definition.enumerator))
170170+171171+;; mod x;
172172+(mod_item (identifier) @local.definition.module)
173173+174174+;; use statements
175175+176176+;; use item;
177177+(use_declaration
178178+ (identifier) @local.import)
179179+180180+;; use path as item;
181181+(use_as_clause
182182+ alias: (identifier) @local.import)
183183+184184+;; use path::item;
185185+(use_declaration
186186+ (scoped_identifier
187187+ name: (identifier) @local.import))
188188+189189+;; use module::{member1, member2, member3};
190190+(use_list
191191+ (identifier) @local.import)
192192+(use_list
193193+ (scoped_identifier
194194+ name: (identifier) @local.import))
195195+196196+197197+;; refs
198198+199199+;; !x
200200+(unary_expression (identifier) @local.reference)
201201+202202+;; &x
203203+(reference_expression (identifier) @local.reference)
204204+205205+;; (x)
206206+(parenthesized_expression (identifier) @local.reference)
207207+208208+;; x?
209209+(try_expression (identifier) @local.reference)
210210+211211+;; a = b
212212+(assignment_expression (identifier) @local.reference)
213213+214214+;; a op b
215215+(binary_expression (identifier) @local.reference)
216216+217217+;; a op= b
218218+(compound_assignment_expr (identifier) @local.reference)
219219+220220+;; a as b
221221+(type_cast_expression (identifier) @local.reference)
222222+223223+;; a()
224224+(call_expression (identifier) @local.reference)
225225+226226+;; Self::foo()
227227+;;
228228+;; `foo` can be resolved
229229+(call_expression
230230+ (scoped_identifier
231231+ (identifier) @_self_type
232232+ (identifier) @local.reference)
233233+ (#match? @_self_type "Self"))
234234+235235+;; self.foo()
236236+;;
237237+;; `foo` can be resolved
238238+(call_expression
239239+ (field_expression
240240+ (self)
241241+ (field_identifier) @local.reference))
242242+243243+;; return a
244244+(return_expression (identifier) @local.reference)
245245+246246+;; break a
247247+(break_expression (identifier) @local.reference)
248248+249249+;; break 'label
250250+(break_expression (loop_label) @local.reference)
251251+252252+;; continue 'label;
253253+(continue_expression (loop_label) @local.reference)
254254+255255+;; yield x;
256256+(yield_expression (identifier) @local.reference)
257257+258258+;; await a
259259+(await_expression (identifier) @local.reference)
260260+261261+;; (a, b)
262262+(tuple_expression (identifier) @local.reference)
263263+264264+;; a[]
265265+(index_expression (identifier) @local.reference)
266266+267267+;; ident;
268268+(expression_statement (identifier) @local.reference)
269269+270270+;; a..b
271271+(range_expression (identifier) @local.reference)
272272+273273+;; [ident; N]
274274+(array_expression (identifier) @local.reference)
275275+276276+;; path::to::item
277277+;;
278278+;; `path` is a ref
279279+(scoped_identifier
280280+ path: (identifier) @local.reference)
281281+282282+;; rhs of let decls
283283+(let_declaration
284284+ value: (identifier) @local.reference)
285285+286286+;; type T = [T; N]
287287+;;
288288+;; N is a ident ref
289289+(array_type
290290+ length: (identifier) @local.reference)
291291+292292+;; S { _ }
293293+(struct_expression
294294+ (type_identifier) @local.reference)
295295+296296+;; S { a }
297297+(struct_expression
298298+ (field_initializer_list
299299+ (shorthand_field_initializer
300300+ (identifier) @local.reference)))
301301+302302+;; S { a: value }
303303+(struct_expression
304304+ (field_initializer_list
305305+ (field_initializer
306306+ (identifier) @local.reference)))
307307+308308+;; S { ..a }
309309+(struct_expression
310310+ (field_initializer_list
311311+ (base_field_initializer
312312+ (identifier) @local.reference)))
313313+314314+;; if a {}
315315+(if_expression (identifier) @local.reference)
316316+317317+;; for pattern in value {}
318318+;;
319319+;; `value` is a ref
320320+(for_expression
321321+ value: (identifier) @local.reference)
322322+323323+;; while a {}
324324+(while_expression (identifier) @local.reference)
325325+326326+;; if let _ = a {}
327327+;;
328328+;; the ident following the `=` is a ref
329329+;; the ident preceding the `=` is a def
330330+;; while let _ = a {}
331331+(let_condition
332332+ "="
333333+ (identifier) @local.reference)
334334+335335+336336+;; match a
337337+(match_expression (identifier) @local.reference)
338338+339339+;; match _ {
340340+;; pattern => a,
341341+;; }
342342+;;
343343+;; this `a` is somehow not any expression form
344344+(match_arm (identifier) @local.reference)
345345+346346+;; a.b
347347+;;
348348+;; `b` is ignored
349349+(field_expression
350350+ (identifier) @local.reference)
351351+352352+;; { stmt; foo }
353353+(block
354354+ (identifier) @local.reference)
355355+356356+;; arguments to method calls or function calls
357357+(arguments
358358+ (identifier) @local.reference)
359359+360360+;; impl S { .. }
361361+(impl_item (type_identifier) @local.reference)
362362+363363+;; where T: ...
364364+(where_predicate
365365+ left: (type_identifier) @local.reference)
366366+367367+;; trait bounds
368368+(trait_bounds
369369+ (type_identifier) @local.reference)
370370+(trait_bounds
371371+ (lifetime) @local.reference)
372372+373373+;; idents in macros
374374+(token_tree
375375+ (identifier) @local.reference)
376376+377377+;; types
378378+379379+;; (T, U)
380380+(tuple_type
381381+ (type_identifier) @local.reference)
382382+383383+;; &T
384384+(reference_type
385385+ (type_identifier) @local.reference)
386386+387387+;; &'a T
388388+(reference_type
389389+ (lifetime) @local.reference)
390390+391391+;; &'a self
392392+(self_parameter
393393+ (lifetime) @local.reference)
394394+395395+;; *mut T
396396+;; *const T
397397+(pointer_type
398398+ (type_identifier) @local.reference)
399399+400400+;; A<_>
401401+(generic_type
402402+ (type_identifier) @local.reference)
403403+404404+;; _<V>
405405+(type_arguments
406406+ (type_identifier) @local.reference)
407407+(type_arguments
408408+ (lifetime) @local.reference)
409409+410410+;; T<U = V>
411411+;;
412412+;; U is ignored
413413+;; V is a ref
414414+(type_binding
415415+ name: (_)
416416+ type: (type_identifier) @local.reference)
417417+418418+;; [T]
419419+(array_type
420420+ (type_identifier) @local.reference)
421421+422422+;; type T = U;
423423+;;
424424+;; T is a def
425425+;; U is a ref
426426+(type_item
427427+ name: (_)
428428+ type: (type_identifier) @local.reference)
429429+430430+(function_item
431431+ return_type: (type_identifier) @local.reference)
432432+433433+;; type refs in params
434434+;;
435435+;; fn _(_: T)
436436+(parameters
437437+ (parameter
438438+ type: (type_identifier) @local.reference))
439439+440440+;; dyn T
441441+(dynamic_type
442442+ (type_identifier) @local.reference)
443443+444444+;; <T>::call()
445445+(bracketed_type
446446+ (type_identifier) @local.reference)
447447+448448+;; T as Trait
449449+(qualified_type
450450+ (type_identifier) @local.reference)
451451+452452+;; module::T
453453+;;
454454+;; `module` is a def
455455+;; `T` is a ref
456456+(scoped_type_identifier
457457+ path: (identifier) @local.reference)
458458+459459+;; struct _ { field: Type }
460460+;; `Type` is a ref
461461+ (field_declaration
462462+ name: (_)
463463+ type: (type_identifier) @local.reference)
+550
src/stag.tsg
···11+[(block)
22+ (declaration_list)
33+ (impl_item)
44+55+ ;; let expressions create scopes
66+ (if_expression
77+ [(let_condition)
88+ (let_chain)])
99+1010+;; each match arm can bind variables with
1111+;; patterns, without creating a block scope;
1212+;;
1313+;; match _ {
1414+;; (a, b) => a,
1515+;; }
1616+;;
1717+;; The bindings for a, b are constrained to
1818+;; the match arm.
1919+ (match_arm)
2020+2121+;; loop labels are defs that are available only
2222+;; within the scope they create:
2323+;;
2424+;; 'outer: loop {
2525+;; let x = 2;
2626+;; };
2727+;; let y = 2;
2828+;;
2929+;; Produces a scope graph like so:
3030+;;
3131+;; {
3232+;; defs: [ y ],
3333+;; scopes: [
3434+;; {
3535+;; defs: [ 'outer ],
3636+;; scopes: [
3737+;; {
3838+;; defs: [ x ]
3939+;; }
4040+;; ]
4141+;; }
4242+;; ]
4343+;; }
4444+;;
4545+ (loop_expression)
4646+ (for_expression)
4747+ (while_expression)] @cap
4848+{
4949+ (scope (range @cap))
5050+}
5151+5252+5353+(function_item
5454+ (identifier) @i
5555+ (parameters) @params
5656+ (block) @body)
5757+{
5858+ (def @i "function")
5959+ (scope (cover @params @body))
6060+}
6161+6262+6363+;; impl items can define types and lifetimes:
6464+;;
6565+;; impl<'a, T> Trait for Struct { .. }
6666+;;
6767+;; in order to constrain those to the impl block,
6868+;; we add a local scope here:
6969+[(struct_item (type_identifier) @i (type_parameters)? @t body: (_) @b)
7070+ (union_item (type_identifier) @i (type_parameters)? @t body: (_) @b)
7171+ (enum_item (type_identifier) @i (type_parameters)? @t body: (_) @b)
7272+ (type_item (type_identifier) @i (type_parameters)? @t type: (_) @b)
7373+ (trait_item (type_identifier) @i (type_parameters)? @t body: (_) @b)]
7474+{
7575+ (def @i)
7676+ (scope (cover @t @b))
7777+ (scope (range @b))
7878+}
7979+8080+8181+;; DEFS
8282+;; ----
8383+8484+;; let x = ...;
8585+(let_declaration pattern: (identifier) @cap)
8686+{
8787+ (def @cap "variable")
8888+}
8989+9090+;; if let x = ...;
9191+;; while let x = ...;
9292+(let_condition (identifier) @cap . "=")
9393+{
9494+ (def @cap "variable")
9595+}
9696+9797+;; let (a, b, ...) = ..;
9898+;; if let (a, b, ...) = {}
9999+;; while let (a, b, ...) = {}
100100+;; match _ { (a, b) => { .. } }
101101+(tuple_pattern (identifier) @cap)
102102+{
103103+ (def @cap "variable")
104104+}
105105+106106+;; Some(a)
107107+(tuple_struct_pattern
108108+ type: (_)
109109+ (identifier) @cap)
110110+{
111111+ (def @cap "variable")
112112+}
113113+114114+;; let S { field: a } = ..;
115115+(struct_pattern
116116+ (field_pattern
117117+ (identifier) @cap))
118118+{
119119+ (def @cap "variable")
120120+}
121121+122122+123123+[
124124+ ;; (mut x: T)
125125+ (mut_pattern (identifier) @i)
126126+127127+ ;; (ref x: T)
128128+ (ref_pattern (identifier) @i)
129129+130130+ ;; const x = ...;
131131+ (const_item (identifier) @i)
132132+133133+ ;; static x = ...;
134134+ (static_item (identifier) @i)]
135135+{
136136+ (def @i "variable")
137137+}
138138+139139+;; fn _(x: _)
140140+(parameters
141141+ (parameter
142142+ pattern: (identifier) @cap))
143143+{
144144+ (def @cap)
145145+}
146146+147147+;; fn _(self)
148148+(parameters
149149+ (self_parameter
150150+ (self) @cap))
151151+{
152152+ (def @cap)
153153+}
154154+155155+;; type parameters
156156+(type_parameters
157157+ (type_identifier) @cap)
158158+{
159159+ (def @cap)
160160+}
161161+(type_parameters
162162+ (lifetime) @cap)
163163+{
164164+ (def @cap)
165165+}
166166+(constrained_type_parameter
167167+ left: (type_identifier) @cap)
168168+{
169169+ (def @cap)
170170+}
171171+172172+;; |x| { ... }
173173+;; no type
174174+(closure_parameters (identifier) @cap)
175175+{
176176+ (def @cap)
177177+}
178178+179179+;; |x: T| { ... }
180180+;; with type
181181+(closure_parameters
182182+ (parameter
183183+ (identifier) @cap))
184184+{
185185+ (def @cap)
186186+}
187187+188188+;; 'outer: loop { .. }
189189+(loop_expression
190190+ (loop_label) @cap)
191191+{
192192+ (def @cap)
193193+}
194194+195195+;; `for` exprs create two defs: a label (if any) and the
196196+;; loop variable
197197+(for_expression . (identifier) @cap)
198198+{
199199+ (def @cap)
200200+}
201201+(for_expression (loop_label) @cap)
202202+{
203203+ (def @cap)
204204+}
205205+206206+;; 'label: while cond { .. }
207207+(while_expression
208208+ (loop_label) @cap)
209209+{
210210+ (def @cap)
211211+}
212212+213213+;; struct and union fields
214214+(field_declaration_list
215215+ (field_declaration
216216+ (field_identifier) @cap))
217217+{
218218+ (def @cap)
219219+}
220220+221221+;; enum variants
222222+(enum_variant_list
223223+ (enum_variant
224224+ (identifier) @cap))
225225+{
226226+ (def @cap)
227227+}
228228+229229+;; mod x;
230230+(mod_item (identifier) @cap)
231231+{
232232+ (def @cap)
233233+}
234234+235235+236236+;; IMPORTS
237237+;; -------
238238+239239+;; use item;
240240+(use_declaration
241241+ (identifier) @cap)
242242+{
243243+ (def @cap)
244244+}
245245+246246+;; use path as item;
247247+(use_as_clause
248248+ alias: (identifier) @cap)
249249+{
250250+ (def @cap)
251251+}
252252+253253+;; use path::item;
254254+(use_declaration
255255+ (scoped_identifier
256256+ name: (identifier) @cap))
257257+{
258258+ (def @cap)
259259+}
260260+261261+;; use module::{member1, member2, member3};
262262+(use_list
263263+ (identifier) @cap)
264264+{
265265+ (def @cap)
266266+}
267267+268268+(use_list
269269+ (scoped_identifier
270270+ name: (identifier) @cap))
271271+{
272272+ (def @cap)
273273+}
274274+275275+276276+;; REFS
277277+;; ----
278278+279279+[
280280+ ;; !x
281281+ (unary_expression (identifier) @cap)
282282+ ;; &x
283283+ (reference_expression (identifier) @cap)
284284+285285+ ;; (x)
286286+ (parenthesized_expression (identifier) @cap)
287287+288288+ ;; x?
289289+ (try_expression (identifier) @cap)
290290+291291+ ;; a = b
292292+ (assignment_expression (identifier) @cap)
293293+294294+ ;; a op b
295295+ (binary_expression (identifier) @cap)
296296+297297+ ;; a op= b
298298+ (compound_assignment_expr (identifier) @cap)
299299+300300+ ;; a as b
301301+ (type_cast_expression (identifier) @cap)
302302+303303+ ;; a()
304304+ (call_expression (identifier) @cap)
305305+306306+ ;; return a
307307+ (return_expression (identifier) @cap)
308308+309309+ ;; break a
310310+ (break_expression (identifier) @cap)
311311+312312+ ;; break 'label
313313+ (break_expression (loop_label) @cap)
314314+315315+ ;; continue 'label;
316316+ (continue_expression (loop_label) @cap)
317317+318318+ ;; yield x;
319319+ (yield_expression (identifier) @cap)
320320+321321+ ;; await a
322322+ (await_expression (identifier) @cap)
323323+324324+ ;; (a, b)
325325+ (tuple_expression (identifier) @cap)
326326+327327+ ;; a[]
328328+ (index_expression (identifier) @cap)
329329+330330+ ;; ident;
331331+ (expression_statement (identifier) @cap)
332332+333333+ ;; a..b
334334+ (range_expression (identifier) @cap)
335335+336336+ ;; [ident; N]
337337+ (array_expression (identifier) @cap)
338338+339339+ ;; path::to::item
340340+ ;;
341341+ ;; `path` is a ref
342342+ (scoped_identifier
343343+ path: (identifier) @cap)
344344+345345+ ;; rhs of let decls
346346+ (let_declaration
347347+ value: (identifier) @cap)
348348+349349+ ;; type T = [T; N]
350350+ ;;
351351+ ;; N is a ident ref
352352+ (array_type
353353+ length: (identifier) @cap)
354354+355355+ ;; S { _ }
356356+ (struct_expression
357357+ (type_identifier) @cap)
358358+359359+ ;; S { a }
360360+ (struct_expression
361361+ (field_initializer_list
362362+ (shorthand_field_initializer
363363+ (identifier) @cap)))
364364+365365+ ;; S { a: value }
366366+ (struct_expression
367367+ (field_initializer_list
368368+ (field_initializer
369369+ (identifier) @cap)))
370370+371371+ ;; S { ..a }
372372+ (struct_expression
373373+ (field_initializer_list
374374+ (base_field_initializer
375375+ (identifier) @cap)))
376376+377377+ ;; if a {}
378378+ (if_expression (identifier) @cap)
379379+380380+ ;; for pattern in value {}
381381+ ;;
382382+ ;; `value` is a ref
383383+ (for_expression
384384+ value: (identifier) @cap)
385385+386386+ ;; while a {}
387387+ (while_expression (identifier) @cap)
388388+389389+ ;; match a
390390+ (match_expression (identifier) @cap)
391391+392392+ ;; match _ {
393393+ ;; pattern => a,
394394+ ;; }
395395+ ;;
396396+ ;; this `a` is somehow not any expression form
397397+ (match_arm (identifier) @cap)
398398+399399+ ;; a.b
400400+ ;;
401401+ ;; `b` is ignored
402402+ (field_expression
403403+ (identifier) @cap)
404404+405405+ ;; { stmt; foo }
406406+ (block
407407+ (identifier) @cap)
408408+409409+ ;; arguments to method calls or function calls
410410+ (arguments
411411+ (identifier) @cap)
412412+413413+ ;; impl S { .. }
414414+ (impl_item (type_identifier) @cap)
415415+416416+ ;; where T: ...
417417+ (where_predicate
418418+ left: (type_identifier) @cap)
419419+420420+ ;; trait bounds
421421+ (trait_bounds
422422+ (type_identifier) @cap)
423423+ (trait_bounds
424424+ (lifetime) @cap)
425425+426426+ ;; idents in macros
427427+ (token_tree
428428+ (identifier) @cap)
429429+430430+431431+ ;; types
432432+433433+ ;; (T, U)
434434+ (tuple_type
435435+ (type_identifier) @cap)
436436+437437+ ;; &T
438438+ (reference_type
439439+ (type_identifier) @cap)
440440+441441+ ;; &'a T
442442+ (reference_type
443443+ (lifetime) @cap)
444444+445445+ ;; &'a self
446446+ (self_parameter
447447+ (lifetime) @cap)
448448+449449+ ;; *mut T
450450+ ;; *const T
451451+ (pointer_type
452452+ (type_identifier) @cap)
453453+454454+ ;; A<_>
455455+ (generic_type
456456+ (type_identifier) @cap)
457457+458458+ ;; _<V>
459459+ (type_arguments
460460+ (type_identifier) @cap)
461461+ (type_arguments
462462+ (lifetime) @cap)
463463+464464+ ;; T<U = V>
465465+ ;;
466466+ ;; U is ignored
467467+ ;; V is a ref
468468+ (type_binding
469469+ name: (_)
470470+ type: (type_identifier) @cap)
471471+472472+ ;; [T]
473473+ (array_type
474474+ (type_identifier) @cap)
475475+476476+ ;; type T = U;
477477+ ;;
478478+ ;; T is a def
479479+ ;; U is a ref
480480+ (type_item
481481+ name: (_)
482482+ type: (type_identifier) @cap)
483483+484484+ (function_item
485485+ return_type: (type_identifier) @cap)
486486+487487+ ;; type refs in params
488488+ ;;
489489+ ;; fn _(_: T)
490490+ (parameters
491491+ (parameter
492492+ type: (type_identifier) @cap))
493493+494494+ ;; dyn T
495495+ (dynamic_type
496496+ (type_identifier) @cap)
497497+498498+ ;; <T>::call()
499499+ (bracketed_type
500500+ (type_identifier) @cap)
501501+502502+ ;; T as Trait
503503+ (qualified_type
504504+ (type_identifier) @cap)
505505+506506+ ;; module::T
507507+ ;;
508508+ ;; `module` is a def
509509+ ;; `T` is a ref
510510+ (scoped_type_identifier
511511+ path: (identifier) @cap)
512512+513513+ ;; struct _ { field: Type }
514514+ ;; `Type` is a ref
515515+ (field_declaration
516516+ name: (_)
517517+ type: (type_identifier) @cap)
518518+519519+ ;; Self::foo()
520520+ ;;
521521+ ;; `foo` can be resolved
522522+ (call_expression
523523+ (scoped_identifier
524524+ (identifier) @_self_type
525525+ (identifier) @cap)
526526+ (#match? @_self_type "Self"))
527527+528528+ ;; self.foo()
529529+ ;;
530530+ ;; `foo` can be resolved
531531+ (call_expression
532532+ (field_expression
533533+ (self)
534534+ (field_identifier) @cap))
535535+536536+ ;; if let _ = a {}
537537+ ;;
538538+ ;; the ident following the `=` is a ref
539539+ ;; the ident preceding the `=` is a def
540540+ ;; while let _ = a {}
541541+ (let_condition
542542+ "="
543543+ .
544544+ (identifier) @cap)
545545+]
546546+{
547547+ (ref @cap)
548548+}
549549+550550+