mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-11-14 16:52:09 +08:00
Java typed a call receiver from a local declaration or a plain field of
the enclosing class only. A field of an outer class read inside an inner
or anonymous class (mHandler.post(...) inside new Runnable() {...}),
Outer.this.f, a chain of fields (this.mOwner.mRepo.save()) and a local
whose type has type arguments fell through to the name-only strategies,
and so did every receiver whose declared type is a library class:
parcel.readInt() on an android.os.Parcel went to a project
VersionedParcel.readInt, list.size() to any project size().
The declared type is now read for each of those shapes, a chain one hop
at a time with each hop's own imports, keeping a written package or
outer class (Map.Entry, play.api.mvc.BodyParser). A receiver whose
declared type the project does not declare, or that an import or a
written package pins outside the project, gets no edge. When no import
decides between same-named types, a Java call prefers the Java
declaration over a Scala or Kotlin one.
Also, from review: a field the class around the call declares is read
as written before the member reader, which keeps only the last name
(PauseTest.Suite, a field written with its package); a local or loop
variable keeps the package its declaration writes; a field typed by a
type parameter goes to its bound, and a class the class head names as
a type argument (Comparable<ApplicationModule>) is not taken for one; a
nested type a superclass declares, or one an on-demand import of its
class names (import play.mvc.Http.*), counts as named; and a typed miss
on a type no project class or interface is named (a URI, an enum's
name()) gets no guess, as on main.
Validation:
- java-receiver-type.test.ts: 19 tests, the PR's 5 red on main; the
other 14 pass on main, and our 8 each fail without their change.
- A/B against main 25776014 (with #2942 and #2950; the same sites
change against 7cceba52), sites added/removed/retargeted: jextract
+2/-1/106, spring-modulith +1/-3/2, Minestom +52/-91/71, SystemUI
+53/-319/96, spring-ai +69/-659/532, kestra-java +5/-504/162,
playframework +0/-196/599; click and gin identical. Of the removed
edges main had at 0.9, 1,004 were wrong (an import oracle plus 16
read by hand) and 4 right (a lambda parameter, two nested types of a
Scala object, a field read under a static import of a same-named
member). Retargets land on the declared type or the supertype
declaring the method, except about 16 build()/clone() calls on
spring-ai's nested option builders, which move from one wrong target
to another.
- Cost (3 interleaved rounds): spring-ai wall 27.9 s on main vs
25.9 s, CPU 90.2 s vs 88.1 s. SystemUI read 71.3 vs 79.4 s wall
under other jobs' load; CPU profiles of both arms put the new code at
about 0.6 s of 115 s.
Original PR #1942 by @danusha2345.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>