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:
Christoph Hegemann 2024-01-05 15:40:34 +01:00 committed by GitHub
parent 2035b9f673
commit 5190cd76e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 467 additions and 377 deletions

View File

@ -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`.

View File

@ -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"))
;

View File

@ -34,7 +34,7 @@
; )
; (method_declaration
; name: (identifier) @definition.function (#set! "scope" "parent")
; name: (identifier) @definition.function
; )

View File

@ -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

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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

View File

@ -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.