2.4 KiB
2.4 KiB
Polyglot Analysis: Supporting Mixed Java and Kotlin
1. The Need for Language Abstraction
Professional JVM codebases are increasingly "Mixed Mode" (Java + Kotlin). Tying our analysis logic directly to JDT (Java AST) creates a bottleneck for Kotlin support.
2. The "Driver" Architecture
We decouple the Intelligence Logic (e.g., "Find all REST controllers") from the AST Parser (e.g., "Walk the JDT tree").
1. Language Driver Interface
public interface LanguageDriver {
boolean supports(Path filePath);
// Unified Extraction Methods
List<RawClassMetadata> extractClasses(Path filePath);
List<RawMethodMetadata> extractMethods(RawClassMetadata cls);
List<RawInvocationMetadata> findInvocations(RawMethodMetadata method, String targetMethodName);
}
2. Unified Metadata Model (Intermediate Representation)
We move to a "Generic JVM Model" before performing the final state machine mapping.
public record RawClassMetadata(
String fqn,
String language, // "java", "kotlin"
List<String> annotations,
String superclass,
List<String> interfaces
) {}
public record RawMethodMetadata(
String name,
List<String> annotations,
String returnType,
List<String> parameterTypes
) {}
3. Polyglot Analysis Flow
- File Discovery: Find all
.javaand.ktfiles. - Driver Assignment: Delegate each file to the appropriate
LanguageDriver. - Cross-Language Resolution: The
CodebaseContextstores metadata for ALL classes.- A Java controller calling a Kotlin service is resolved by looking up the Kotlin class's unified metadata.
- Enricher Execution: Enrichers (like
SpringMvcEnricher) now operate on the Unified Metadata Model, making them language-agnostic!
4. Why this is "Future Proof":
- Enrichers are written once: The logic to find
@PostMappingonly needs to know how to query theRawClassMetadataannotations, not how to traverse JDT vs. Kotlin PSI. - Easy Expansion: To support Scala, Groovy, or even a newer Java version, you just add a new
LanguageDriver.
5. Refactoring Plan
- Define Intermediate Models: Create
RawClassMetadataandRawMethodMetadata. - Extract JDT Logic: Move the current JDT-specific code into
JavaLanguageDriver. - Kotlin PoC (Phase 12): Implement a basic
KotlinLanguageDriverusing Regex or a lightweight parser (like Tree-Sitter) to prove the abstraction works.