Loading
feat(code-graph): introduce cross-language symbol resolution via language families
What does this MR do and why?
Closes #576 (closed), related to #337 (closed), #354 (closed). Languages that share resolution semantics (C/C++, Java/Kotlin, JS/TS) can now resolve symbols across each other's files. Before this MR, every language got an isolated graph -- a Kotlin file importing a Java class resolved to nothing. Now they share one.
┌──────────────────────────────┐
│ group_parseable_inventory │
│ │
│ │
│ .java ─┐ .py ──┐ │
│ .kt ───┤ .rb ──┤ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────┐ ┌──────────┤
│ │ JVM │ │Standalone│
│ │ family │ │ families │
└────┴────┬────┘────└─────┬────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────┐
│ FamilyPipeline │ │FamilyPipeline│
│ │ │ (1 member) │
│ Java spec ─┐ │ │ │
│ Kotlin spec┤ │ │ Python spec │
│ ▼ │ │ │ │
│ ┌────────────┐│ │ ┌────▼────┐ │
│ │ Shared ││ │ │ Single │ │
│ │ CodeGraph ││ │ │CodeGraph│ │
│ └────────────┘│ │ └─────────┘ │
└─────────────────┘ └──────────────┘How it works
- Files are grouped by family instead of language. Java + Kotlin files land in the same bucket.
FamilyPipelineparses each file with its language-specific grammar (tree-sitter-java for.java, tree-sitter-kotlin for.kt) but feeds all definitions into one sharedCodeGraph.- Resolution uses per-file rules against the unified symbol table. A Kotlin file's import of
com.example.model.Userfinds the Java class definition because they're in the same graph. - Single-language families (Python, Ruby, Go, etc.) delegate directly to
FamilyPipelinewith a one-entry member map --GenericPipelineis now an 8-line wrapper, not a 430-line duplicate.
Resolution directionality
Cross-language resolution can be asymmetric. This falls out of per-file rules naturally -- no special directional logic:
Java ◄──────────► Kotlin Bidirectional (same bytecode, same package resolution)
C ◄───────────── C++ One-way (C grammar has no classes/namespaces)
JS ◄────────────► TS Bidirectional (same module system)A C file won't accidentally resolve a C++ class because C's resolution rules don't have scope rules for classes.
Families shipped in this MR
| Family | Members | Proven by |
|---|---|---|
CFamily |
C | Existing C test suites (C++ joins when its MR lands) |
Jvm |
Java, Kotlin | New jvm/cross_language_resolution.yaml -- Kotlin calling Java static methods, Java calling Kotlin constructors, bidirectional |
Standalone |
Python, Ruby, Go, Rust, C#, JS, TS | All 136 existing tests pass unchanged |
Safety
- FQN separator mismatch between family members asserts at construction (e.g. can't put Java
.and C::in the same family) - Primary context selection is deterministic (lexicographic sort by language name)
- Custom-pipeline languages (JS, Rust) that can't provide a
LanguageContexttrigger fallback to per-language dispatch lang_ctx_foris auto-generated by theregister_v2_pipelines!macro -- adding a new language to the macro table is all that's needed
What's next
- C++ MR adds
CpptoCFamilywith cross-language.cpp->.hresolution test - Web family (JS + TS) -- requires
JsPipelineto implementlang_ctx - FFI edge stitching for incompatible resolution models (Python/C, Java/C via JNI) -- tracked in #575 (closed)
Edited by Michael Usachenko