feat(jvm): resolve Java/Kotlin imports by fully-qualified name (#412)
Wrap top-level declarations of `.kt` / `.java` files in an implicit `namespace` node carrying the file's `package`, then resolve `import com.example.foo.Bar` through that qualifiedName index — so a Bar in Models.kt resolves correctly regardless of filename, a top-level function import binds to its declaration, Java↔Kotlin interop crosses cleanly, and same-name classes across packages no longer collide. Wildcard imports still go through name-matcher.
Also extracts Java/C# anonymous-class overrides (`new T() { ... }`) as first-class class nodes with their override methods. Phase 5.5 interface-impl then bridges T's abstract methods to the anonymous overrides automatically — including the lambda-returned `new T() { ... }` pattern common in guava (Splitter, CacheBuilder).
Concrete impact on macrozheng/mall (524 .java files, multi-module Spring + MyBatis): 524 namespace nodes, 862 imports edges newly resolve to Java symbols, 76 distinct `Criteria` classes preserved across packages with no merge. On google/guava (3,227 .java): 3,608 anonymous classes extracted, +2,534 interface-impl edges reach overrides hidden in `new T() { ... }` blocks.
Agent A/B playbook on small (spring-petclinic-kotlin, 38 .kt), medium (mall, 524 .java), large (guava, 3,227 .java) — 3 flow prompts × 2 runs/arm × 2 arms = 36 runs, claude-opus, headless. Spring repos: 0/0 Read/Grep with-arm, −27% wall-clock vs no-codegraph. Guava: 1.8 Read avg with-arm (vs 2.0 without) — improved by the anon-class extraction; residual is a lambda→SAM coverage gap orthogonal to FQN imports (filing follow-up).
This commit is contained in:
@@ -212,4 +212,16 @@ export interface LanguageExtractor {
|
||||
* Returns the callee name if this node is a bare call, or undefined if not.
|
||||
*/
|
||||
extractBareCall?: (node: SyntaxNode, source: string) => string | undefined;
|
||||
|
||||
/**
|
||||
* Node types representing a file-level package/namespace declaration
|
||||
* (e.g. Kotlin `package_header`, Java `package_declaration`). When set,
|
||||
* the core wraps every top-level declaration in an implicit `namespace`
|
||||
* node carrying the FQN, so cross-file import resolution can match by
|
||||
* qualifiedName instead of filename (Kotlin filename ≠ class name).
|
||||
*/
|
||||
packageTypes?: string[];
|
||||
|
||||
/** Extract the dotted package name from a package declaration node. */
|
||||
extractPackage?: (node: SyntaxNode, source: string) => string | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user