A call whose receiver is itself a call — a factory / singleton / builder that returns an object — should produce a calls edge to the chained method:
Foo.getInstance().bar(); // bar() should resolve to Foo::bar
This was fixed for C++ (#645) and PHP (#608). A probe of the other statically-typed README languages found the same gap in all of them — and in 7 of the 9 the chained method currently resolves to the wrong class (a same-named method on an unrelated type), which is a correctness bug, not just missing coverage.
The fix is the 3-part #645/#608 mechanism, per language: capture the factory's declared return type, preserve the chained receiver at extraction, then resolve and validate the chained method on the inferred type — so a wrong inference produces no edge, never a wrong one.
| Language |
Probe result (Foo.factory().method()) |
Status |
| Java |
edge missing |
✅ #751 |
| Kotlin |
wrong edge → same-named decoy |
✅ #752 |
| C# |
edge missing |
✅ #753 |
| Swift |
wrong edge → same-named decoy |
✅ #755 |
| Rust |
wrong edge → same-named decoy |
✅ #757 |
| Go |
wrong edge → same-named decoy (same-package New().Method(); cross-package pkg.New() was #469) |
⬜ |
| Scala |
wrong edge → same-named decoy |
⬜ |
| Dart |
wrong edge → same-named decoy (factory-constructor call also unresolved) |
⬜ |
| TypeScript |
wrong edge → same-named decoy |
⬜ |
Dynamically-typed languages can't use this approach (no declared return types to read): Ruby and plain JS are out of scope; Python is partial (optional -> T hints, see #578).
Each language is validated the same way before merge: synthetic decoy + absent-method safety tests, then a real-repo A/B on a public OSS repo (node count unchanged, 0 edges lost, +N chained edges recovered, precision spot-checked).
A call whose receiver is itself a call — a factory / singleton / builder that returns an object — should produce a
callsedge to the chained method:This was fixed for C++ (#645) and PHP (#608). A probe of the other statically-typed README languages found the same gap in all of them — and in 7 of the 9 the chained method currently resolves to the wrong class (a same-named method on an unrelated type), which is a correctness bug, not just missing coverage.
The fix is the 3-part #645/#608 mechanism, per language: capture the factory's declared return type, preserve the chained receiver at extraction, then resolve and validate the chained method on the inferred type — so a wrong inference produces no edge, never a wrong one.
Foo.factory().method())New().Method(); cross-packagepkg.New()was #469)Dynamically-typed languages can't use this approach (no declared return types to read): Ruby and plain JS are out of scope; Python is partial (optional
-> Thints, see #578).Each language is validated the same way before merge: synthetic decoy + absent-method safety tests, then a real-repo A/B on a public OSS repo (node count unchanged, 0 edges lost, +N chained edges recovered, precision spot-checked).