Skip to content

Kotlin: remap builtins on Java-origin method/field types#7428

Merged
timtebeek merged 3 commits intomainfrom
tim/kotlin-remap-params
Apr 28, 2026
Merged

Kotlin: remap builtins on Java-origin method/field types#7428
timtebeek merged 3 commits intomainfrom
tim/kotlin-remap-params

Conversation

@timtebeek
Copy link
Copy Markdown
Member

@timtebeek timtebeek commented Apr 19, 2026

Summary

KotlinTypeMapping applied remapKotlinBuiltin to supertypes, interfaces, generic bounds, and annotations in #7364, but not to method parameter/return/receiver types or field types — so a Kotlin call to a Jackson JsonGenerationException("msg", cause, gen) constructor produced parameter types kotlin.String / kotlin.Throwable, and a MethodMatcher written against the JVM FQNs failed to match. Per review, the remap is scoped to methods/fields whose declaring class is FirJavaClass (third-party Java libraries on the classpath); Kotlin-declared signatures like kotlin.io.ConsoleKt.println(kotlin.Any) and user properties keep their author-intended Kotlin builtin names. JDK classes go through Kotlin's classfile loader as a different FIR type and are out of scope here — recipes targeting JDK signatures over Kotlin code need a Kotlin-aware MethodMatcher.

Test plan

  • ./gradlew :rewrite-kotlin:test passes
  • New constructorParameterTypesRemapKotlinBuiltinsForJavaOrigin test asserts Jackson's JsonGenerationException(String, Throwable, JsonGenerator) surfaces JVM FQNs and a Java-FQN MethodMatcher matches
  • Existing assertions for Kotlin-declared methods (println, methodInvocationWithDefaults) unchanged — they still expect kotlin.* parameter types

`KotlinTypeMapping` applied `remapKotlinBuiltin` to supertypes,
interfaces, generic bounds, and annotations in #7364, but not to
method parameter types, return types, receiver types, or field
types. A Kotlin `IllegalArgumentException("msg", cause)` therefore
produced a constructor whose parameter types were `kotlin.String` /
`kotlin.Throwable`, so a `MethodMatcher` written against the Java
FQNs (`java.lang.String` / `java.lang.Throwable`) failed to match on
Kotlin sources even though the bytecode signature is identical.

Wire `remapKotlinBuiltin` through both `methodDeclarationType` and
`methodInvocationType` (parameter types, return type, receiver) and
through `variableType` (field/property type).
}
""",
spec -> spec.afterRecipe(cu -> {
var matcher = new MethodMatcher("java.lang.IllegalArgumentException <constructor>(String, Throwable)");
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem we saw was specifically with MethodMatcher not being KotlinTypeUtils aware, and hence seeing Kotlin types here instead of their Java equivalents.

public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, AtomicBoolean atomicBoolean) {
if ("println".equals(method.getSimpleName())) {
assertThat(method.getMethodType().toString()).isEqualTo("kotlin.io.ConsoleKt{name=println,return=void,parameters=[kotlin.Any]}");
assertThat(method.getMethodType().toString()).isEqualTo("kotlin.io.ConsoleKt{name=println,return=void,parameters=[java.lang.Object]}");
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I'm a bit doubtful; do we really want to map all Kotlin types to their Java equivalents, even for packages like kotlin.io ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose not all Kotlin types have a direct Java equivalent. E.g. Nothing?
So I guess the answer would be no? For consistency.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scoped to Java-origin classes (FirJavaClass) in 97295cd. The motivating Jackson case still works; Kotlin-declared signatures like kotlin.io.ConsoleKt.println(kotlin.Any) are now preserved. JDK classes go through Kotlin's classfile loader as a different FIR type, so they're out of scope here — that'd need a Kotlin-aware MethodMatcher.

@timtebeek timtebeek marked this pull request as ready for review April 21, 2026 05:40
Copy link
Copy Markdown
Contributor

@greg-at-moderne greg-at-moderne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Following review on #7428, only remap kotlin.* parameter/return/field
types when the declaring class is a FirJavaClass (third-party Java
libraries on the classpath). Kotlin-declared signatures —
`kotlin.io.ConsoleKt.println(kotlin.Any)`, user properties of type
`String`, etc. — keep their author-intended Kotlin builtin names.

The motivating case (#7427) is Jackson's JsonGenerationException,
which is FirJavaClass; the test now uses that directly. JDK classes
go through Kotlin's classfile loader as something other than
FirJavaClass and are out of scope here — recipes that target JDK
signatures over Kotlin code need a Kotlin-aware MethodMatcher.
@timtebeek timtebeek changed the title Kotlin: remap builtins on method parameter, return, and variable types Kotlin: remap builtins on Java-origin method/field types Apr 28, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Apr 28, 2026
@timtebeek timtebeek merged commit 6a1ac1b into main Apr 28, 2026
1 check passed
@timtebeek timtebeek deleted the tim/kotlin-remap-params branch April 28, 2026 13:49
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

KotlinTypeMapping: remapKotlinBuiltin not applied to method parameter types

2 participants