fix(parser): extract all names from grouped var/const specs

extractGoVarConst used ChildByFieldName("name"), which returns only the first name field, so 'var a, b = 1, 2' and 'const ( C, D = 3, 4 )' surfaced only a/C. Iterate every "name"-field child so each declared identifier becomes its own symbol. Adds TestExtractGoVarConstMultiName.
This commit is contained in:
2026-06-20 00:33:31 +01:00
parent a0b41a6eb8
commit b0c1fc0480
2 changed files with 49 additions and 3 deletions
+11 -3
View File
@@ -152,12 +152,20 @@ func extractGoVarConst(n *sitter.Node, content []byte, filename string) []protoc
WalkTree(n, func(node *sitter.Node) bool {
if node.Type() == "const_spec" || node.Type() == "var_spec" {
nameNode := node.ChildByFieldName("name")
if nameNode != nil {
// A spec may declare multiple names (e.g. var a, b = 1, 2);
// ChildByFieldName returns only the first, so iterate all "name" fields.
for i := 0; i < int(node.ChildCount()); i++ {
if node.FieldNameForChild(i) != "name" {
continue
}
nameNode := node.Child(i)
if nameNode == nil {
continue
}
symbols = append(symbols, protocol.Symbol{
Name: GetNodeText(nameNode, content),
Kind: kind,
Location: NodeLocation(node, filename),
Location: NodeLocation(nameNode, filename),
})
}
}
+38
View File
@@ -123,6 +123,44 @@ var globalVar = "test"
}
}
// Grouped var/const specs declare multiple names on one spec (var a, b = 1, 2);
// every name must surface as its own symbol, not just the first.
func TestExtractGoVarConstMultiName(t *testing.T) {
r := NewRegistry()
defer r.Close()
content := `package main
var a, b = 1, 2
const (
C, D = 3, 4
)
`
ctx := context.Background()
result, err := r.Parse(ctx, "test.go", []byte(content))
if err != nil {
t.Fatalf("parse failed: %v", err)
}
symbols := ExtractSymbols(result.Tree, []byte(content), protocol.LangGo, "test.go")
want := map[string]protocol.SymbolKind{
"a": protocol.SymbolVariable,
"b": protocol.SymbolVariable,
"C": protocol.SymbolConstant,
"D": protocol.SymbolConstant,
}
got := make(map[string]protocol.SymbolKind)
for _, sym := range symbols {
got[sym.Name] = sym.Kind
}
for name, kind := range want {
if got[name] != kind {
t.Errorf("symbol %q: got kind %q, want %q (symbols: %+v)", name, got[name], kind, symbols)
}
}
}
func TestExtractJSSymbols(t *testing.T) {
r := NewRegistry()
defer r.Close()