feat(code-graph): extract package-level var and const in go
What does this MR do and why?
Extracts package-level var and const declarations in Go as structural Definition nodes in the knowledge graph.
Previously, the Go code indexer handled var_spec and const_spec strictly as local scope bindings. While this enabled internal reference resolution, it prevented exported constants and sentinel errors (e.g. var ErrNotFound = errors.New("not found")) from being emitted as persistent Definition nodes.
This MR adds new scope rules to the Go DSL that elevate package-level variables and constants to graph entities.
Related Issues
Closes #671 (closed)
Testing
Verified by adding a new integration test fixture crates/integration-tests-codegraph/fixtures/go/var_const.yaml) which asserts that var and const definitions are successfully extracted. The changes were validated locally by runnin cargo nextest run -p integration-tests-codegraph.
Performance Analysis
This MR shouldn't introduce any performance regression. The extraction of these declarations utilizes the existing tree-sitter AST visitation pass without introducing new pipeline stages or heavy allocations.
- This merge request does not introduce any performance regression. If a performance regression is expected, explain why.
Agent context — long-form analysis, file-by-file walkthroughs, profiler output, alternatives considered
Implementation Details:
- Added
var_specandconst_specto the scopes array incrates/code-graph/src/v2/langs/generic/go.rs. var_specis mapped toDefKind::Propertyandconst_specis mapped toDefKind::EnumEntry.- Both scopes use
no_scope()since variable declarations do not introduce new lexical blocks for children. - Applied the structural predicate
.when(!ancestor_is(&["function_declaration", "method_declaration", "func_literal"]))to ensure that only package-level variables are elevated to the graph. This successfully prevents local function variables from cluttering the database as definitions. - Tree-sitter parses grouped declarations (e.g.
var ( A = 1 \n B = 2 )) as individualvar_specnodes under a parentvar_declaration. Because our scope rules targetvar_specdirectly, they naturally handle grouped package declarations without requiring any custom flattening logic.