fix(java): walk a field's initializer scoped to the field (#693 for Java)

`extractField` minted the field node and stopped; the dispatcher then only
scanned the `field_declaration` subtree for function-as-value candidates. So
a field initializer's code was never walked:

    private final Runnable fieldLambda = () -> target();          // no caller
    private final Runnable l = new LocationListener() { … };       // invisible
    private final int eager = compute();                           // no caller

The anonymous-class form lost more than edges — the class and its overrides
were never extracted at all, which is how `Parcelable.Creator` and every
Android listener field is written.

Fix: walk the declarator's `value` through visitFunctionBody with the field
pushed on the scope stack — Go's #693/#744 fix, and the same shape as the
TS/JS class-field walk already sitting in the methodTypes branch (#808).
`extractField` is shared, but the walk is keyed on the `value` FIELD, which
only Java's `variable_declarator` carries: C# (bare child), VB.NET
(`initializer`) and PHP (`default_value`, separate branch) are untouched and
stay for their own turn.

Kernel and TS extractor move together, so kernel parity stays byte-identical.

Measured on the 409-file DJI MSDK v5 UX SDK (Java): strictly additive, 0 lost
nodes / edges / refs, +21 nodes (anonymous listener and Creator classes with
their overrides), +21 edges, +651 refs, 409/409 files still byte-parity
between the two arms.
This commit is contained in:
danusha2345
2026-08-05 22:26:11 +03:00
parent cf582f4274
commit 468f623745
5 changed files with 66 additions and 0 deletions
+10
View File
@@ -751,6 +751,16 @@ impl<'t> Walker<'t> {
if let Some(row) = row {
self.extract_decorators_for(node, row);
self.extract_type_annotations(node, row);
// Walk the initializer ATTRIBUTED to the declared field
// (#693, the Go fix): the dispatcher only fn-ref-scans this
// subtree, so a lambda / method reference / anonymous class
// in `private final Runnable r = () -> target();` emitted no
// call edge at all.
if let Some(value) = decl.child_by_field_name("value") {
self.stack.push(Scope { row, kind: field_kind, name: name.clone() });
self.visit_function_body(value);
self.stack.pop();
}
}
}
} else {