fix(jvm): resolve mixed Java/Kotlin callgraph edges#684
Conversation
fb96853 to
e6f8c2a
Compare
Before: Java/Kotlin cross-file LSP emitted package-shaped JVM names while graph nodes stayed path-derived, and member calls like receiver.method did not consume LSP overrides. After: Java and Kotlin share package-indexed JVM defs across mixed Gradle/Maven source roots, normalize JVM defs to declared packages for LSP registries, consume qualified member-call overrides by leaf name, and assert both Java-to-Kotlin and Kotlin-to-Java lsp CALLS edges. Why: /home/dat/ica/server mixes src/main/java and src/main/kotlin in the same JVM packages; path-prefix filtering missed same-package defs and fallback suffix matching produced weaker or wrong call edges. Verify: make -f Makefile.cbm test -> 5705 passed. Signed-off-by: nguyentamdat <nguyentamdat@gmail.com>
e6f8c2a to
f33f068
Compare
|
Huge thanks for opening this PR and for the work you put into it. The maintainer shop is currently full, so this may sit for a bit before it gets a proper review. We will come back to this as soon as possible with real feedback; I wanted to make sure it did not sit unacknowledged in the meantime. |
|
Thank you — the root cause is real and the fix uses the correct convention: the declared package is JVM ground truth, and mixed src/main/java + src/main/kotlin roots genuinely can't be joined by path-derived module QNs. Your red-first test (asserting strategy:lsp both directions AND absence of the weaker suffix strategy) is exactly how we like guards written, and splitting the low-RAM change into #685 was appreciated. One question before merge, not a blocker: the cbm_pipeline_lsp_target_node tail-match fallback applies to all languages, not just JVM — ambiguity returns NULL and the full suite is green, so the residual risk is a single wrong-module tail coincidence in a non-JVM language. Would you gate it to JVM languages, or do you have a case where the global fallback recovers real edges elsewhere? Happy either way with a one-line rationale. Update: to get this into the next release, if we don't hear back on the gating question in the next couple of days we'll default to gating the tail-match fallback to JVM languages in a small follow-up on top of your branch and merge — with your commits landing as-is and full credit. If you have a case where the global fallback recovers real edges, just say so and we'll merge it ungated instead. |
|
Thank you — the root cause was real and your fix used the correct convention: the declared package is JVM ground truth, and your red-first test (asserting strategy:lsp both directions AND the absence of the weaker suffix strategy) is exactly how we like guards written. We carried it over the line with one addition per the review thread: the new tail-match fallbacks are now gated to JVM languages (rationale: unique Class.method leaf matching is safe under JVM class-per-file package semantics; elsewhere one wrong-module coincidence would fabricate an edge), with a guard test for the gate itself. Merged as 5f6461e (PR #818) with you credited as co-author. Splitting the low-RAM change into #685 earlier was appreciated — that one stays open on its own merits. Thanks again! |
…ages Mixed Gradle/Maven source roots (src/main/java + src/main/kotlin) share JVM packages that path-derived module QNs cannot join: cross-file LSP emitted package-shaped names while graph nodes stayed path-derived, and same-package defs across roots were filtered out, so Java<->Kotlin calls fell back to weak or wrong textual edges. The declared package is JVM ground truth. Normalize JVM defs to their declared package (inferring it from conventional source roots only when no package was extracted), index defs by declared namespace alongside the path module so same-package defs survive per-file filtering, restrict JVM callers to JVM defs, register cross-def return-type signatures for Kotlin receiver typing, and consume qualified member-call overrides by leaf name in the parallel lsp_idx fast path. Distilled from DeusData#684 with one design change: the new unique-Class.method tail-match fallbacks in lsp_resolve.h are gated to JVM callers (cbm_pipeline_lsp_allow_tail_match, Java/Kotlin only). Tail-matching by unique leaf is safe where class-per-file package semantics hold; in other languages a single wrong-module coincidence would fabricate a CALLS edge. The leaf-key lsp_idx lookup stays global: it aligns the fast path with the build-side key that already used leaf names. Tests: carried mixed Java/Kotlin regression (red on main, green here) plus a gate guard asserting the tail fallbacks stay off for non-JVM callers and on for JVM. Co-authored-by: nguyentamdat <nguyentamdat@gmail.com> Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Thanks for carrying this over the line and for preserving the credit. JVM-only gating for the tail-match fallback makes sense to me: the fallback was intended to recover declared-package/class-method drift in Java/Kotlin, and I don’t have a concrete non-JVM case that needs the global behavior. Appreciate the clear rationale and the extra guard test. |
Summary
src/main/java,src/main/kotlin,src/test/java, andsrc/test/kotlinroots for Java/Kotlin fileslsp_idxpathstrategy: lspedges for Java -> Kotlin and Kotlin -> Java callsVerification
make -f Makefile.cbm test->5726 passedNotes
Split out from the original bundled branch so this PR now contains only the JVM callgraph fix. The low-RAM indexing change is now separate in #685.