mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 18:31:54 +00:00
Improves locals queries for Go (#59320)
Stops recording top-level functions and var bindings as locals with our Go queries. To allow skipping top-level var bindings I adds the skip feature to the locals DSL. Also adds tests for various Go language features
This commit is contained in:
parent
2035b9f673
commit
5190cd76e9
@ -96,6 +96,30 @@ def f():
|
||||
a = 4 # reference 1
|
||||
```
|
||||
|
||||
### Skipping definitions
|
||||
|
||||
Because we want to exclude non-local definitions when collecting locals, it's possible to mark a definition as `@definition.skip`.
|
||||
This will make it so the definition is not included in the output and all future matches of it will be skipped.
|
||||
It's important that you specify skip matches _before_ regular definition matches.
|
||||
|
||||
```scm
|
||||
;; Skip top-level var_spec definitions
|
||||
(source_file (var_spec (identifier) @definition.skip))
|
||||
|
||||
;; Captures all var_spec definitions as definitions
|
||||
(var_spec (identifier) @definition)
|
||||
```
|
||||
|
||||
```go
|
||||
// Will be skipped
|
||||
var top_level = 10
|
||||
|
||||
func main() {
|
||||
// Will be recorded as a local
|
||||
var local = 10
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
References are specified by labeling a capture as a `@reference`.
|
||||
|
||||
@ -2,25 +2,47 @@
|
||||
(function_declaration) @scope
|
||||
(method_declaration) @scope
|
||||
(expression_switch_statement) @scope
|
||||
;: See https://gobyexample.com/if-else for why if_statements need an
|
||||
;; extra scope other than the blocks they open
|
||||
(expression_case) @scope
|
||||
;; if_statement needs to open an extra scope, because you can define
|
||||
;; variables inside an if in go:
|
||||
;; if num := 10; num > 3 {
|
||||
;; ..
|
||||
;; } else {
|
||||
;; ..
|
||||
;; }
|
||||
(if_statement) @scope
|
||||
(for_statement) @scope
|
||||
(block) @scope
|
||||
|
||||
(source_file
|
||||
(var_declaration
|
||||
(var_spec name: (identifier) @definition.skip)))
|
||||
|
||||
(var_spec
|
||||
name: (identifier) @definition.var)
|
||||
|
||||
(short_var_declaration
|
||||
left: (expression_list (identifier) @definition.term))
|
||||
|
||||
;; TODO: We should talk about these: they could be params instead
|
||||
(source_file
|
||||
(const_declaration
|
||||
(const_spec
|
||||
name: (identifier) @definition.skip)))
|
||||
|
||||
(const_declaration
|
||||
(const_spec
|
||||
name: (identifier) @definition.var))
|
||||
|
||||
(parameter_declaration name: (identifier) @definition.term)
|
||||
(variadic_parameter_declaration (identifier) @definition.var)
|
||||
|
||||
(function_declaration
|
||||
name: ((identifier) @definition.function
|
||||
(#set! "hoist" "function")
|
||||
(#set! "scope" "global")))
|
||||
|
||||
((method_declaration name: (field_identifier) @definition.method))
|
||||
;; This syntax is only allowed to define top-level functions,
|
||||
;; which we consider as non-locals, so we don't want to track these
|
||||
;; here.
|
||||
;;
|
||||
;; (function_declaration
|
||||
;; name: ((identifier) @definition.function)
|
||||
;; (#set! "hoist" "function"))
|
||||
|
||||
;; import (
|
||||
;; f "fmt"
|
||||
@ -31,45 +53,11 @@
|
||||
(import_spec
|
||||
name: (package_identifier) @definition.namespace))
|
||||
|
||||
(var_spec
|
||||
name: (identifier) @definition.var)
|
||||
|
||||
(for_statement
|
||||
(range_clause
|
||||
left: (expression_list
|
||||
(identifier) @definition.var)))
|
||||
|
||||
(const_declaration
|
||||
(const_spec
|
||||
name: (identifier) @definition.var))
|
||||
|
||||
(type_declaration
|
||||
(type_spec
|
||||
name: (type_identifier) @definition.type))
|
||||
|
||||
(identifier) @reference
|
||||
(type_identifier) @reference
|
||||
(field_identifier) @reference
|
||||
|
||||
; ;; Call references
|
||||
; ((call_expression
|
||||
; function: (identifier) @reference)
|
||||
; (set! reference.kind "call"))
|
||||
;
|
||||
; ((call_expression
|
||||
; function: (selector_expression
|
||||
; field: (field_identifier) @reference))
|
||||
; (set! reference.kind "call"))
|
||||
;
|
||||
;
|
||||
; ((call_expression
|
||||
; function: (parenthesized_expression
|
||||
; (identifier) @reference))
|
||||
; (set! reference.kind "call"))
|
||||
;
|
||||
; ((call_expression
|
||||
; function: (parenthesized_expression
|
||||
; (selector_expression
|
||||
; field: (field_identifier) @reference)))
|
||||
; (set! reference.kind "call"))
|
||||
;
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
; )
|
||||
|
||||
; (method_declaration
|
||||
; name: (identifier) @definition.function (#set! "scope" "parent")
|
||||
; name: (identifier) @definition.function
|
||||
; )
|
||||
|
||||
|
||||
|
||||
@ -6,15 +6,12 @@
|
||||
|
||||
(assignment
|
||||
left: (identifier) @definition.var
|
||||
(#set! "reassignment_behavior" "oldest_is_definition")
|
||||
(#set! "def_ref"))
|
||||
(global_operator
|
||||
(identifier) @definition.var
|
||||
(#set! "reassignment_behavior" "oldest_is_definition")
|
||||
(#set! "def_ref"))
|
||||
(persistent_operator
|
||||
(identifier) @definition.var
|
||||
(#set! "reassignment_behavior" "oldest_is_definition")
|
||||
(#set! "def_ref"))
|
||||
|
||||
(function_definition
|
||||
|
||||
@ -37,25 +37,9 @@ use tree_sitter::Node;
|
||||
// references we'll probably make it so `@reference` with no
|
||||
// namespace matches definitions in any namespace and
|
||||
// `@definition` matches any `@reference.namespace`
|
||||
//
|
||||
// b) Marking globals to avoid emitting them into occurrences
|
||||
//
|
||||
// https://github.com/sourcegraph/sourcegraph/issues/57791
|
||||
//
|
||||
// I've given this an initial try, but tree-sitter queries are
|
||||
// difficult to work with.
|
||||
//
|
||||
// The main problem is that `(source_file (child) @global)` captures
|
||||
// all occurences of `(child)` regardless of depth and nesting
|
||||
// underneath `source_file`. This makes it very difficult to talk
|
||||
// about "toplevel" items. We might need to extend our DSL a little
|
||||
// further and do some custom tree-traversal logic to implement this.
|
||||
//
|
||||
// One possible idea could be to subtract any matches we'd get from
|
||||
// scip-ctags
|
||||
|
||||
// The maximum number of parent scopes we traverse before giving up to
|
||||
// prevent infinite loops
|
||||
/// The maximum number of parent scopes we traverse before giving up to
|
||||
/// prevent infinite loops
|
||||
const MAX_SCOPE_DEPTH: i32 = 10000;
|
||||
|
||||
pub fn find_locals(
|
||||
@ -241,6 +225,10 @@ struct LocalResolver<'a> {
|
||||
// definitions. Ideally we'd fix our queries to prevent these
|
||||
// overlaps.
|
||||
skip_references_at_offsets: HashSet<usize>,
|
||||
// When marking captures as @definition.skip we record them here,
|
||||
// to not record any subsequent matches. This is used to filter
|
||||
// out non-local definitions
|
||||
skip_definitions_at_offsets: HashSet<usize>,
|
||||
occurrences: Vec<Occurrence>,
|
||||
}
|
||||
|
||||
@ -266,6 +254,7 @@ impl<'a> LocalResolver<'a> {
|
||||
source_bytes,
|
||||
definition_id_supply: 0,
|
||||
skip_references_at_offsets: HashSet::new(),
|
||||
skip_definitions_at_offsets: HashSet::new(),
|
||||
occurrences: vec![],
|
||||
}
|
||||
}
|
||||
@ -510,6 +499,7 @@ impl<'a> LocalResolver<'a> {
|
||||
}
|
||||
|
||||
fn collect_captures(
|
||||
&mut self,
|
||||
config: &'a LocalConfiguration,
|
||||
tree: &'a tree_sitter::Tree,
|
||||
source_bytes: &'a [u8],
|
||||
@ -534,6 +524,18 @@ impl<'a> LocalResolver<'a> {
|
||||
node: capture.node,
|
||||
})
|
||||
} else if capture_name.starts_with("definition") {
|
||||
let offset = capture.node.start_byte();
|
||||
if self.skip_definitions_at_offsets.contains(&offset) {
|
||||
continue;
|
||||
}
|
||||
let kind = capture_name
|
||||
.strip_prefix("definition.")
|
||||
.unwrap_or(capture_name);
|
||||
if kind == "skip" {
|
||||
self.skip_references_at_offsets.insert(offset);
|
||||
self.skip_definitions_at_offsets.insert(offset);
|
||||
continue;
|
||||
}
|
||||
let is_def_ref = properties.iter().any(|p| p.key.as_ref() == "def_ref");
|
||||
let mut hoist = None;
|
||||
if let Some(prop) = properties.iter().find(|p| p.key.as_ref() == "hoist") {
|
||||
@ -716,7 +718,7 @@ impl<'a> LocalResolver<'a> {
|
||||
test_writer: Option<&mut dyn Write>,
|
||||
) -> Vec<Occurrence> {
|
||||
// First we collect all captures from the tree-sitter locals query
|
||||
let captures = Self::collect_captures(config, tree, self.source_bytes);
|
||||
let captures = self.collect_captures(config, tree, self.source_bytes);
|
||||
|
||||
// Next we build a tree structure of scopes and definitions
|
||||
let top_scope = self
|
||||
@ -779,62 +781,42 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_go() {
|
||||
fn go() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Go).unwrap();
|
||||
let source_code = include_str!("../testdata/locals.go");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
insta::assert_snapshot!("go_occurrences", dumped);
|
||||
insta::assert_snapshot!("go_scopes", scope_tree);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_nested_locals() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Go).unwrap();
|
||||
let source_code = include_str!("../testdata/locals-nested.go");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_functions() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Go).unwrap();
|
||||
let source_code = include_str!("../testdata/funcs.go");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_perl() {
|
||||
fn perl() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Perl).unwrap();
|
||||
let source_code = include_str!("../testdata/perl.pm");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
insta::assert_snapshot!("perl_occurrences", dumped);
|
||||
insta::assert_snapshot!("perl_scopes", scope_tree);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_matlab() {
|
||||
fn matlab() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Matlab).unwrap();
|
||||
let source_code = include_str!("../testdata/locals.m");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
insta::assert_snapshot!("matlab_occurrences", dumped);
|
||||
insta::assert_snapshot!("matlab_scopes", scope_tree);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_do_java() {
|
||||
fn java() {
|
||||
let config = crate::languages::get_local_configuration(BundledParser::Java).unwrap();
|
||||
let source_code = include_str!("../testdata/locals.java");
|
||||
let (doc, scope_tree) = parse_file_for_lang(config, source_code);
|
||||
let dumped = snapshot_syntax_document(&doc, source_code);
|
||||
insta::assert_snapshot!(dumped);
|
||||
insta::assert_snapshot!(scope_tree);
|
||||
insta::assert_snapshot!("java_occurrences", dumped);
|
||||
insta::assert_snapshot!("java_scopes", scope_tree);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: scope_tree
|
||||
---
|
||||
scope global (0, 0)-(27, 0)
|
||||
hoisted_def Something (7, 5)-(7, 14)
|
||||
hoisted_def Another (12, 5)-(12, 12)
|
||||
def f (3, 1)-(3, 2)
|
||||
scope scope (7, 0)-(10, 1)
|
||||
ref Something (7, 5)-(7, 14)
|
||||
scope scope (7, 17)-(10, 1)
|
||||
def y (8, 1)-(8, 2)
|
||||
ref y (8, 1)-(8, 2)
|
||||
ref f (9, 1)-(9, 2)
|
||||
ref Println (9, 3)-(9, 10)
|
||||
ref y (9, 20)-(9, 21)
|
||||
scope scope (12, 0)-(26, 1)
|
||||
ref Another (12, 5)-(12, 12)
|
||||
scope scope (12, 15)-(26, 1)
|
||||
ref Something (13, 1)-(13, 10)
|
||||
scope scope (14, 1)-(16, 2)
|
||||
scope scope (14, 9)-(16, 2)
|
||||
def x (15, 2)-(15, 3)
|
||||
ref x (15, 2)-(15, 3)
|
||||
scope scope (17, 1)-(22, 2)
|
||||
scope scope (17, 9)-(22, 2)
|
||||
def x (18, 2)-(18, 3)
|
||||
ref x (18, 2)-(18, 3)
|
||||
scope scope (19, 2)-(21, 3)
|
||||
scope scope (19, 10)-(21, 3)
|
||||
def x (20, 3)-(20, 4)
|
||||
ref x (20, 3)-(20, 4)
|
||||
scope scope (23, 1)-(25, 2)
|
||||
scope scope (23, 9)-(25, 2)
|
||||
def x (24, 2)-(24, 3)
|
||||
ref x (24, 2)-(24, 3)
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: dumped
|
||||
---
|
||||
package example
|
||||
|
||||
import (
|
||||
f "fmt"
|
||||
// ^ definition local 1
|
||||
"github.com/sourcegraph/"
|
||||
)
|
||||
|
||||
func Something() {
|
||||
// ^^^^^^^^^ definition local 2
|
||||
y := ", world"
|
||||
// ^ definition local 3
|
||||
f.Println("hello", y)
|
||||
// ^ reference local 1
|
||||
// ^ reference local 3
|
||||
}
|
||||
|
||||
func Another() {
|
||||
// ^^^^^^^ definition local 4
|
||||
Something()
|
||||
// ^^^^^^^^^ reference local 2
|
||||
if true {
|
||||
x := true
|
||||
// ^ definition local 5
|
||||
}
|
||||
if true {
|
||||
x := true
|
||||
// ^ definition local 6
|
||||
if true {
|
||||
x := true
|
||||
// ^ definition local 7
|
||||
}
|
||||
}
|
||||
if true {
|
||||
x := true
|
||||
// ^ definition local 8
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: scope_tree
|
||||
---
|
||||
scope global (0, 0)-(14, 0)
|
||||
hoisted_def main (2, 5)-(2, 9)
|
||||
hoisted_def Another (11, 5)-(11, 12)
|
||||
scope scope (2, 0)-(9, 1)
|
||||
ref main (2, 5)-(2, 9)
|
||||
scope scope (2, 12)-(9, 1)
|
||||
def local (3, 1)-(3, 6)
|
||||
ref local (3, 1)-(3, 6)
|
||||
def something (4, 1)-(4, 10)
|
||||
ref something (4, 1)-(4, 10)
|
||||
scope scope (4, 14)-(6, 2)
|
||||
def local (4, 19)-(4, 24)
|
||||
ref local (4, 19)-(4, 24)
|
||||
ref int (4, 25)-(4, 28)
|
||||
ref int (4, 30)-(4, 33)
|
||||
scope scope (4, 34)-(6, 2)
|
||||
ref local (5, 9)-(5, 14)
|
||||
ref println (8, 1)-(8, 8)
|
||||
ref local (8, 9)-(8, 14)
|
||||
ref something (8, 16)-(8, 25)
|
||||
scope scope (11, 0)-(13, 1)
|
||||
ref Another (11, 5)-(11, 12)
|
||||
def local (11, 13)-(11, 18)
|
||||
ref local (11, 13)-(11, 18)
|
||||
ref int (11, 19)-(11, 22)
|
||||
ref int (11, 24)-(11, 27)
|
||||
scope scope (11, 28)-(13, 1)
|
||||
ref local (12, 8)-(12, 13)
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: dumped
|
||||
---
|
||||
package main
|
||||
|
||||
func main() {
|
||||
// ^^^^ definition local 1
|
||||
local := true
|
||||
// ^^^^^ definition local 2
|
||||
something := func(local int) int {
|
||||
// ^^^^^^^^^ definition local 3
|
||||
// ^^^^^ definition local 4
|
||||
return local
|
||||
// ^^^^^ reference local 4
|
||||
}
|
||||
|
||||
println(local, something)
|
||||
// ^^^^^ reference local 2
|
||||
// ^^^^^^^^^ reference local 3
|
||||
}
|
||||
|
||||
func Another(local int) int {
|
||||
// ^^^^^^^ definition local 5
|
||||
// ^^^^^ definition local 6
|
||||
return local
|
||||
// ^^^^^ reference local 6
|
||||
}
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: scope_tree
|
||||
---
|
||||
scope global (0, 0)-(18, 0)
|
||||
hoisted_def main (2, 5)-(2, 9)
|
||||
scope scope (2, 0)-(17, 1)
|
||||
ref main (2, 5)-(2, 9)
|
||||
scope scope (2, 12)-(17, 1)
|
||||
def local (3, 1)-(3, 6)
|
||||
ref local (3, 1)-(3, 6)
|
||||
def something (4, 1)-(4, 10)
|
||||
ref something (4, 1)-(4, 10)
|
||||
scope scope (4, 14)-(14, 2)
|
||||
def unrelated (4, 19)-(4, 28)
|
||||
ref unrelated (4, 19)-(4, 28)
|
||||
ref int (4, 29)-(4, 32)
|
||||
ref int (4, 34)-(4, 37)
|
||||
scope scope (4, 38)-(14, 2)
|
||||
def superNested (5, 2)-(5, 13)
|
||||
ref superNested (5, 2)-(5, 13)
|
||||
scope scope (5, 17)-(7, 3)
|
||||
def deeplyNested (5, 22)-(5, 34)
|
||||
ref deeplyNested (5, 22)-(5, 34)
|
||||
ref int (5, 35)-(5, 38)
|
||||
ref int (5, 40)-(5, 43)
|
||||
scope scope (5, 44)-(7, 3)
|
||||
ref local (6, 10)-(6, 15)
|
||||
ref unrelated (6, 18)-(6, 27)
|
||||
ref deeplyNested (6, 30)-(6, 42)
|
||||
def overwriteName (9, 2)-(9, 15)
|
||||
ref overwriteName (9, 2)-(9, 15)
|
||||
scope scope (9, 19)-(11, 3)
|
||||
def local (9, 24)-(9, 29)
|
||||
ref local (9, 24)-(9, 29)
|
||||
ref int (9, 30)-(9, 33)
|
||||
ref int (9, 35)-(9, 38)
|
||||
scope scope (9, 39)-(11, 3)
|
||||
ref local (10, 10)-(10, 15)
|
||||
ref unrelated (10, 18)-(10, 27)
|
||||
ref superNested (13, 9)-(13, 20)
|
||||
ref overwriteName (13, 26)-(13, 39)
|
||||
ref println (16, 1)-(16, 8)
|
||||
ref local (16, 9)-(16, 14)
|
||||
ref something (16, 16)-(16, 25)
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: dumped
|
||||
---
|
||||
package main
|
||||
|
||||
func main() {
|
||||
// ^^^^ definition local 1
|
||||
local := 5
|
||||
// ^^^^^ definition local 2
|
||||
something := func(unrelated int) int {
|
||||
// ^^^^^^^^^ definition local 3
|
||||
// ^^^^^^^^^ definition local 4
|
||||
superNested := func(deeplyNested int) int {
|
||||
// ^^^^^^^^^^^ definition local 5
|
||||
// ^^^^^^^^^^^^ definition local 6
|
||||
return local + unrelated + deeplyNested
|
||||
// ^^^^^ reference local 2
|
||||
// ^^^^^^^^^ reference local 4
|
||||
// ^^^^^^^^^^^^ reference local 6
|
||||
}
|
||||
|
||||
overwriteName := func(local int) int {
|
||||
// ^^^^^^^^^^^^^ definition local 7
|
||||
// ^^^^^ definition local 8
|
||||
return local + unrelated
|
||||
// ^^^^^ reference local 8
|
||||
// ^^^^^^^^^ reference local 4
|
||||
}
|
||||
|
||||
return superNested(1) + overwriteName(1)
|
||||
// ^^^^^^^^^^^ reference local 5
|
||||
// ^^^^^^^^^^^^^ reference local 7
|
||||
}
|
||||
|
||||
println(local, something)
|
||||
// ^^^^^ reference local 2
|
||||
// ^^^^^^^^^ reference local 3
|
||||
}
|
||||
|
||||
@ -0,0 +1,141 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: dumped
|
||||
---
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Not actually local
|
||||
var local = 10
|
||||
|
||||
func main() {
|
||||
local = 20
|
||||
local := 5
|
||||
// ^^^^^ definition local 1
|
||||
something := func(unrelated int) int {
|
||||
// ^^^^^^^^^ definition local 2
|
||||
// ^^^^^^^^^ definition local 3
|
||||
superNested := func(deeplyNested int) int {
|
||||
// ^^^^^^^^^^^ definition local 4
|
||||
// ^^^^^^^^^^^^ definition local 5
|
||||
return local + unrelated + deeplyNested
|
||||
// ^^^^^ reference local 1
|
||||
// ^^^^^^^^^ reference local 3
|
||||
// ^^^^^^^^^^^^ reference local 5
|
||||
}
|
||||
|
||||
overwriteName := func(local int) int {
|
||||
// ^^^^^^^^^^^^^ definition local 6
|
||||
// ^^^^^ definition local 7
|
||||
return local + unrelated
|
||||
// ^^^^^ reference local 7
|
||||
// ^^^^^^^^^ reference local 3
|
||||
}
|
||||
|
||||
return superNested(1) + overwriteName(1)
|
||||
// ^^^^^^^^^^^ reference local 4
|
||||
// ^^^^^^^^^^^^^ reference local 6
|
||||
}
|
||||
|
||||
println(local, something)
|
||||
// ^^^^^ reference local 1
|
||||
// ^^^^^^^^^ reference local 2
|
||||
}
|
||||
|
||||
func ifFn(local int) int {
|
||||
// ^^^^^ definition local 8
|
||||
if local := 9; local < 0 {
|
||||
// ^^^^^ definition local 9
|
||||
// ^^^^^ reference local 9
|
||||
fmt.Println(local, "is negative")
|
||||
// ^^^^^ reference local 9
|
||||
} else if local < 10 {
|
||||
// ^^^^^ reference local 9
|
||||
fmt.Println(local, "has 1 digit")
|
||||
// ^^^^^ reference local 9
|
||||
} else {
|
||||
fmt.Println(local, "has multiple digits")
|
||||
// ^^^^^ reference local 9
|
||||
}
|
||||
return local
|
||||
// ^^^^^ reference local 8
|
||||
}
|
||||
|
||||
func switchFn(local int) int {
|
||||
// ^^^^^ definition local 10
|
||||
switch x := 0; x {
|
||||
// ^ definition local 11
|
||||
// ^ reference local 11
|
||||
case 0:
|
||||
x := "local x"
|
||||
// ^ definition local 12
|
||||
fmt.Println(x)
|
||||
// ^ reference local 12
|
||||
case 1:
|
||||
fmt.Println(x)
|
||||
// ^ reference local 11
|
||||
case x:
|
||||
// ^ reference local 11
|
||||
fmt.Println("something")
|
||||
}
|
||||
return local
|
||||
// ^^^^^ reference local 10
|
||||
}
|
||||
|
||||
func forFn(local int) int {
|
||||
// ^^^^^ definition local 13
|
||||
for i := 0; i < 3; i++ {
|
||||
// ^ definition local 14
|
||||
// ^ reference local 14
|
||||
// ^ reference local 14
|
||||
fmt.Println(i)
|
||||
// ^ reference local 14
|
||||
}
|
||||
return local
|
||||
// ^^^^^ reference local 13
|
||||
|
||||
}
|
||||
|
||||
func constFunc() int {
|
||||
const LOCAL_CONST = 10
|
||||
// ^^^^^^^^^^^ definition local 15
|
||||
return LOCAL_CONST
|
||||
// ^^^^^^^^^^^ reference local 15
|
||||
}
|
||||
|
||||
func assignmentFn(arg int) int {
|
||||
// ^^^ definition local 16
|
||||
local := 0
|
||||
// ^^^^^ definition local 17
|
||||
local = 1
|
||||
// ^^^^^ reference local 17
|
||||
local[arg] = 2
|
||||
// ^^^^^ reference local 17
|
||||
// ^^^ reference local 16
|
||||
*local = 3
|
||||
// ^^^^^ reference local 17
|
||||
}
|
||||
|
||||
type MyStruct struct {
|
||||
field1 int
|
||||
field2 string
|
||||
}
|
||||
|
||||
type MyInterface interface {
|
||||
method(param int) int
|
||||
// ^^^^^ definition local 18
|
||||
}
|
||||
|
||||
func (m *MyStruct) method(local int) int {
|
||||
// ^ definition local 19
|
||||
// ^^^^^ definition local 20
|
||||
return m.field1 + local
|
||||
// ^ reference local 19
|
||||
// ^^^^^ reference local 20
|
||||
}
|
||||
|
||||
const MY_CONST int = 10
|
||||
|
||||
@ -0,0 +1,162 @@
|
||||
---
|
||||
source: crates/scip-syntax/src/locals.rs
|
||||
expression: scope_tree
|
||||
---
|
||||
scope global (0, 0)-(85, 0)
|
||||
ref local (7, 4)-(7, 9)
|
||||
scope scope (9, 0)-(25, 1)
|
||||
ref main (9, 5)-(9, 9)
|
||||
scope scope (9, 12)-(25, 1)
|
||||
ref local (10, 1)-(10, 6)
|
||||
def local (11, 1)-(11, 6)
|
||||
ref local (11, 1)-(11, 6)
|
||||
def something (12, 1)-(12, 10)
|
||||
ref something (12, 1)-(12, 10)
|
||||
scope scope (12, 14)-(22, 2)
|
||||
def unrelated (12, 19)-(12, 28)
|
||||
ref unrelated (12, 19)-(12, 28)
|
||||
ref int (12, 29)-(12, 32)
|
||||
ref int (12, 34)-(12, 37)
|
||||
scope scope (12, 38)-(22, 2)
|
||||
def superNested (13, 2)-(13, 13)
|
||||
ref superNested (13, 2)-(13, 13)
|
||||
scope scope (13, 17)-(15, 3)
|
||||
def deeplyNested (13, 22)-(13, 34)
|
||||
ref deeplyNested (13, 22)-(13, 34)
|
||||
ref int (13, 35)-(13, 38)
|
||||
ref int (13, 40)-(13, 43)
|
||||
scope scope (13, 44)-(15, 3)
|
||||
ref local (14, 10)-(14, 15)
|
||||
ref unrelated (14, 18)-(14, 27)
|
||||
ref deeplyNested (14, 30)-(14, 42)
|
||||
def overwriteName (17, 2)-(17, 15)
|
||||
ref overwriteName (17, 2)-(17, 15)
|
||||
scope scope (17, 19)-(19, 3)
|
||||
def local (17, 24)-(17, 29)
|
||||
ref local (17, 24)-(17, 29)
|
||||
ref int (17, 30)-(17, 33)
|
||||
ref int (17, 35)-(17, 38)
|
||||
scope scope (17, 39)-(19, 3)
|
||||
ref local (18, 10)-(18, 15)
|
||||
ref unrelated (18, 18)-(18, 27)
|
||||
ref superNested (21, 9)-(21, 20)
|
||||
ref overwriteName (21, 26)-(21, 39)
|
||||
ref println (24, 1)-(24, 8)
|
||||
ref local (24, 9)-(24, 14)
|
||||
ref something (24, 16)-(24, 25)
|
||||
scope scope (27, 0)-(36, 1)
|
||||
ref ifFn (27, 5)-(27, 9)
|
||||
def local (27, 10)-(27, 15)
|
||||
ref local (27, 10)-(27, 15)
|
||||
ref int (27, 16)-(27, 19)
|
||||
ref int (27, 21)-(27, 24)
|
||||
scope scope (27, 25)-(36, 1)
|
||||
scope scope (28, 1)-(34, 2)
|
||||
def local (28, 4)-(28, 9)
|
||||
ref local (28, 4)-(28, 9)
|
||||
ref local (28, 16)-(28, 21)
|
||||
scope scope (28, 26)-(30, 2)
|
||||
ref fmt (29, 2)-(29, 5)
|
||||
ref Println (29, 6)-(29, 13)
|
||||
ref local (29, 14)-(29, 19)
|
||||
scope scope (30, 8)-(34, 2)
|
||||
ref local (30, 11)-(30, 16)
|
||||
scope scope (30, 22)-(32, 2)
|
||||
ref fmt (31, 2)-(31, 5)
|
||||
ref Println (31, 6)-(31, 13)
|
||||
ref local (31, 14)-(31, 19)
|
||||
scope scope (32, 8)-(34, 2)
|
||||
ref fmt (33, 2)-(33, 5)
|
||||
ref Println (33, 6)-(33, 13)
|
||||
ref local (33, 14)-(33, 19)
|
||||
ref local (35, 8)-(35, 13)
|
||||
scope scope (38, 0)-(49, 1)
|
||||
ref switchFn (38, 5)-(38, 13)
|
||||
def local (38, 14)-(38, 19)
|
||||
ref local (38, 14)-(38, 19)
|
||||
ref int (38, 20)-(38, 23)
|
||||
ref int (38, 25)-(38, 28)
|
||||
scope scope (38, 29)-(49, 1)
|
||||
scope scope (39, 1)-(47, 2)
|
||||
def x (39, 8)-(39, 9)
|
||||
ref x (39, 8)-(39, 9)
|
||||
ref x (39, 16)-(39, 17)
|
||||
scope scope (40, 1)-(43, 0)
|
||||
def x (41, 2)-(41, 3)
|
||||
ref x (41, 2)-(41, 3)
|
||||
ref fmt (42, 2)-(42, 5)
|
||||
ref Println (42, 6)-(42, 13)
|
||||
ref x (42, 14)-(42, 15)
|
||||
scope scope (43, 1)-(45, 0)
|
||||
ref fmt (44, 2)-(44, 5)
|
||||
ref Println (44, 6)-(44, 13)
|
||||
ref x (44, 14)-(44, 15)
|
||||
scope scope (45, 1)-(47, 0)
|
||||
ref x (45, 6)-(45, 7)
|
||||
ref fmt (46, 2)-(46, 5)
|
||||
ref Println (46, 6)-(46, 13)
|
||||
ref local (48, 8)-(48, 13)
|
||||
scope scope (51, 0)-(57, 1)
|
||||
ref forFn (51, 5)-(51, 10)
|
||||
def local (51, 11)-(51, 16)
|
||||
ref local (51, 11)-(51, 16)
|
||||
ref int (51, 17)-(51, 20)
|
||||
ref int (51, 22)-(51, 25)
|
||||
scope scope (51, 26)-(57, 1)
|
||||
scope scope (52, 1)-(54, 2)
|
||||
def i (52, 5)-(52, 6)
|
||||
ref i (52, 5)-(52, 6)
|
||||
ref i (52, 13)-(52, 14)
|
||||
ref i (52, 20)-(52, 21)
|
||||
scope scope (52, 24)-(54, 2)
|
||||
ref fmt (53, 2)-(53, 5)
|
||||
ref Println (53, 6)-(53, 13)
|
||||
ref i (53, 14)-(53, 15)
|
||||
ref local (55, 8)-(55, 13)
|
||||
scope scope (59, 0)-(62, 1)
|
||||
ref constFunc (59, 5)-(59, 14)
|
||||
ref int (59, 17)-(59, 20)
|
||||
scope scope (59, 21)-(62, 1)
|
||||
def LOCAL_CONST (60, 7)-(60, 18)
|
||||
ref LOCAL_CONST (60, 7)-(60, 18)
|
||||
ref LOCAL_CONST (61, 8)-(61, 19)
|
||||
scope scope (64, 0)-(69, 1)
|
||||
ref assignmentFn (64, 5)-(64, 17)
|
||||
def arg (64, 18)-(64, 21)
|
||||
ref arg (64, 18)-(64, 21)
|
||||
ref int (64, 22)-(64, 25)
|
||||
ref int (64, 27)-(64, 30)
|
||||
scope scope (64, 31)-(69, 1)
|
||||
def local (65, 1)-(65, 6)
|
||||
ref local (65, 1)-(65, 6)
|
||||
ref local (66, 1)-(66, 6)
|
||||
ref local (67, 1)-(67, 6)
|
||||
ref arg (67, 7)-(67, 10)
|
||||
ref local (68, 2)-(68, 7)
|
||||
ref MyStruct (71, 5)-(71, 13)
|
||||
ref field1 (72, 1)-(72, 7)
|
||||
ref int (72, 8)-(72, 11)
|
||||
ref field2 (73, 1)-(73, 7)
|
||||
ref string (73, 8)-(73, 14)
|
||||
ref MyInterface (76, 5)-(76, 16)
|
||||
ref method (77, 1)-(77, 7)
|
||||
def param (77, 8)-(77, 13)
|
||||
ref param (77, 8)-(77, 13)
|
||||
ref int (77, 14)-(77, 17)
|
||||
ref int (77, 19)-(77, 22)
|
||||
scope scope (80, 0)-(82, 1)
|
||||
def m (80, 6)-(80, 7)
|
||||
ref m (80, 6)-(80, 7)
|
||||
ref MyStruct (80, 9)-(80, 17)
|
||||
ref method (80, 19)-(80, 25)
|
||||
def local (80, 26)-(80, 31)
|
||||
ref local (80, 26)-(80, 31)
|
||||
ref int (80, 32)-(80, 35)
|
||||
ref int (80, 37)-(80, 40)
|
||||
scope scope (80, 41)-(82, 1)
|
||||
ref m (81, 8)-(81, 9)
|
||||
ref field1 (81, 10)-(81, 16)
|
||||
ref local (81, 19)-(81, 24)
|
||||
ref MY_CONST (84, 6)-(84, 14)
|
||||
ref int (84, 15)-(84, 18)
|
||||
|
||||
@ -54,7 +54,6 @@ pub fn captures_to_kind(kind: &Option<&String>) -> symbol_information::Kind {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Converts a SCIP symbol kind to the ctags format.
|
||||
//
|
||||
// Universal-ctags uses inconsistent kind names for the same concept (for example typealias for
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
f "fmt"
|
||||
"github.com/sourcegraph/"
|
||||
)
|
||||
|
||||
func Something() {
|
||||
y := ", world"
|
||||
f.Println("hello", y)
|
||||
}
|
||||
|
||||
func Another() {
|
||||
Something()
|
||||
if true {
|
||||
x := true
|
||||
}
|
||||
if true {
|
||||
x := true
|
||||
if true {
|
||||
x := true
|
||||
}
|
||||
}
|
||||
if true {
|
||||
x := true
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
local := 5
|
||||
something := func(unrelated int) int {
|
||||
superNested := func(deeplyNested int) int {
|
||||
return local + unrelated + deeplyNested
|
||||
}
|
||||
|
||||
overwriteName := func(local int) int {
|
||||
return local + unrelated
|
||||
}
|
||||
|
||||
return superNested(1) + overwriteName(1)
|
||||
}
|
||||
|
||||
println(local, something)
|
||||
}
|
||||
@ -1,14 +1,85 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Not actually local
|
||||
var local = 10
|
||||
|
||||
func main() {
|
||||
local := true
|
||||
something := func(local int) int {
|
||||
return local
|
||||
local = 20
|
||||
local := 5
|
||||
something := func(unrelated int) int {
|
||||
superNested := func(deeplyNested int) int {
|
||||
return local + unrelated + deeplyNested
|
||||
}
|
||||
|
||||
overwriteName := func(local int) int {
|
||||
return local + unrelated
|
||||
}
|
||||
|
||||
return superNested(1) + overwriteName(1)
|
||||
}
|
||||
|
||||
println(local, something)
|
||||
}
|
||||
|
||||
func Another(local int) int {
|
||||
func ifFn(local int) int {
|
||||
if local := 9; local < 0 {
|
||||
fmt.Println(local, "is negative")
|
||||
} else if local < 10 {
|
||||
fmt.Println(local, "has 1 digit")
|
||||
} else {
|
||||
fmt.Println(local, "has multiple digits")
|
||||
}
|
||||
return local
|
||||
}
|
||||
|
||||
func switchFn(local int) int {
|
||||
switch x := 0; x {
|
||||
case 0:
|
||||
x := "local x"
|
||||
fmt.Println(x)
|
||||
case 1:
|
||||
fmt.Println(x)
|
||||
case x:
|
||||
fmt.Println("something")
|
||||
}
|
||||
return local
|
||||
}
|
||||
|
||||
func forFn(local int) int {
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(i)
|
||||
}
|
||||
return local
|
||||
|
||||
}
|
||||
|
||||
func constFunc() int {
|
||||
const LOCAL_CONST = 10
|
||||
return LOCAL_CONST
|
||||
}
|
||||
|
||||
func assignmentFn(arg int) int {
|
||||
local := 0
|
||||
local = 1
|
||||
local[arg] = 2
|
||||
*local = 3
|
||||
}
|
||||
|
||||
type MyStruct struct {
|
||||
field1 int
|
||||
field2 string
|
||||
}
|
||||
|
||||
type MyInterface interface {
|
||||
method(param int) int
|
||||
}
|
||||
|
||||
func (m *MyStruct) method(local int) int {
|
||||
return m.field1 + local
|
||||
}
|
||||
|
||||
const MY_CONST int = 10
|
||||
|
||||
@ -27,7 +27,6 @@ thread_local! {
|
||||
pub(crate) static SYNTAX_SET: SyntaxSet = SyntaxSet::load_defaults_newlines();
|
||||
}
|
||||
|
||||
|
||||
/// Struct from: internal/gosyntect/gosyntect.go
|
||||
///
|
||||
/// Keep in sync with that struct.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user