When a Kotlin source file invokes a top-level extension function from a library on the classpath (e.g. com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()), the resulting J.MethodInvocation has getMethodType() == null whenever KotlinParser resolves the classpath via a TypeTable-synthesized directory rather than the original jar. As a result, MethodMatcher and UsesMethod cannot match the call, even though the import is present.
This affects any recipe that needs to recognize Kotlin top-level functions, including the mod CLI flow that ships LSTs with TypeTable-derived classpaths.
Workaround
Recipes that need to detect such calls have to fall back to looser preconditions (e.g. UsesType on a return type, or scanning the compilation unit for the import) until the underlying TypeTable round-trip is fixed. The precondition list in MigrateMapperSettersToBuilder.java is a concrete example.
Fix
- Stopping the
TypeTable writer from filtering out ACC_SYNTHETIC methods (Kotlin extension functions compile to public static final synthetic on a *Kt facade).
- Capturing the
InnerClasses attribute on round-tripped classes so Kotlin FIR can resolve methods whose `@kotlin.Metadata.d1` protobuf references inner classes.
- Persisting
META-INF/*.kotlin_module resources alongside synthesized .class files so the resolver can find each top-level function's facade owner.
When a Kotlin source file invokes a top-level extension function from a library on the classpath (e.g.
com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()), the resultingJ.MethodInvocationhasgetMethodType() == nullwheneverKotlinParserresolves the classpath via aTypeTable-synthesized directory rather than the original jar. As a result,MethodMatcherandUsesMethodcannot match the call, even though the import is present.This affects any recipe that needs to recognize Kotlin top-level functions, including the
modCLI flow that ships LSTs with TypeTable-derived classpaths.Workaround
Recipes that need to detect such calls have to fall back to looser preconditions (e.g.
UsesTypeon a return type, or scanning the compilation unit for the import) until the underlyingTypeTableround-trip is fixed. The precondition list inMigrateMapperSettersToBuilder.javais a concrete example.Fix
TypeTablewriter from filtering outACC_SYNTHETICmethods (Kotlin extension functions compile topublic static final syntheticon a*Ktfacade).InnerClassesattribute on round-tripped classes so Kotlin FIR can resolve methods whose`@kotlin.Metadata.d1`protobuf references inner classes.META-INF/*.kotlin_moduleresources alongside synthesized.classfiles so the resolver can find each top-level function's facade owner.