fix(scala): walk a val/var initializer scoped to the declared symbol (#693 for Scala)

The val/var hook minted the node and returned true, so the dispatcher only
scanned the subtree for function-as-value candidates and the initializer's
code was never walked:

    val fieldLambda: () => Unit = () => target()   // no caller
    val direct = target()                          // no caller
    lazy val lazily = compute()                    // no caller
    val anon = new Runnable { def run() = target() }  // no caller

Scala puts almost everything in a val, so this is not an edge case: on a
32-file SpinalHDL project the graph was missing 812 references.

Fix: walk the `value` field through visitFunctionBody with the declared symbol
pushed on the scope stack — the same shape as Go's #693/#744 fix, which the
grammar supports directly here (`val_definition` exposes `value`).

Kernel and TS extractor move together; kernel parity holds.

Measured on that SpinalHDL project: 0 lost refs, 0 re-attributed, +812 new,
node and edge counts unchanged (824/792), 32/32 files byte-parity between the
two arms.
This commit is contained in:
danusha2345
2026-08-05 23:13:23 +03:00
parent 8b2e43613c
commit a86703bc79
5 changed files with 59 additions and 0 deletions
+12
View File
@@ -652,6 +652,18 @@ impl<'t> Walker<'t> {
if let (Some(row), Some(t)) = (created, type_node) {
self.emit_scala_type_refs(t, row);
}
// Walk the initializer ATTRIBUTED to the declared symbol
// (#693, the Go fix): the hook consumes this subtree and the
// dispatcher only fn-ref-scans it, so `val cb = () => target()`
// — and even a plain `val x = compute()` — emitted no call edge
// at all.
if let Some(row) = created {
if let Some(value) = node.child_by_field_name("value") {
self.stack.push(Scope { row, kind, name: name.clone() });
self.visit_body(value);
self.stack.pop();
}
}
true
}
"enum_case_definitions" => {