fix(jvm): resolve mixed Java/Kotlin callgraph edges via declared packages#818
Open
DeusData wants to merge 2 commits into
Open
fix(jvm): resolve mixed Java/Kotlin callgraph edges via declared packages#818DeusData wants to merge 2 commits into
DeusData wants to merge 2 commits into
Conversation
…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 #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>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Distilled from #684 (author: @nguyentamdat) — fixes missing/wrong CALLS edges in mixed Java/Kotlin projects, with one design change decided during review: the new unique-tail fallbacks are gated to JVM callers.
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 JVM names while graph nodes stayed path-derived, and same-package defs across roots were dropped by per-file module filtering, so Java ↔ Kotlin calls degraded to weak or wrong textual edges.Changes
pass_lsp_cross.c): JVM defs are normalized to their declared package viapxc_jvm_def_qn;pxc_infer_jvm_namespaceinfers the package from conventional source roots only when no declaredpackagewas extracted.pass_lsp_cross.c/.h):CBMModuleDefIndexgains anamespace_ht(declared package → defs) alongside the path-module index, so JVM same-package defs survive per-file filtering across source roots. JVM callers are restricted to JVM defs.lsp_resolve.h) — the design decision on top of fix(jvm): resolve mixed Java/Kotlin callgraph edges #684: the new unique-Class.method-tail fallbacks incbm_pipeline_find_lsp_resolutionandcbm_pipeline_lsp_target_nodeonly fire when the calling file's language is Java or Kotlin (cbm_pipeline_lsp_allow_tail_match). Tail-matching by unique leaf is safe where class-per-file package semantics hold (JVM); in other languages a single wrong-module coincidence would fabricate a CALLS edge. The leaf-keylsp_idxlookup inpass_parallel.cstays global — it aligns the fast path with the build-side key that already used leaf names.kotlin_lsp.c): cross-file defs register return-type signatures so receiver typing resolves chained Java ↔ Kotlin member calls.pass_parallel.c): Java/Kotlin files run cross-LSP whenever calls exist — per-file LSP can fillresolved_callswith same-file entries while a mixed-root call remains unresolved.Tests
parallel_java_kotlin_lsp_override_cross_file_emits_lsp_strategy_edges(carried from fix(jvm): resolve mixed Java/Kotlin callgraph edges #684): mixedsrc/main/java+src/main/kotlinfixture assertsstrategy: lspCALLS edges Java → Kotlin and Kotlin → Java. Red onmain(fails at the Java → Kotlin strategy assertion), green with this change.parallel_lsp_tail_match_fallbacks_gated_to_jvm(new, guards the gate): the same wrong-module tail coincidence must resolve with the gate open (JVM) and must NOT with the gate closed. Verified red both when the gate policy is widened and when the in-function guards are bypassed. A natural end-to-end non-JVM coincidence fixture is impractical (reaching the fallbacks requires LSP/extraction QN-prefix drift, which single-root languages don't produce), so the gated branches are exercised directly — noted in the test comment.Verification
make -f Makefile.cbm cbm—-Werrorcleanmake -f Makefile.cbm lint-ci— clean./build/c/test-runner lang_contract parallel go_lsp py_lsp ts_lsp java_lsp kotlin_lsp— 630 passed, 0 failed