Skip to content

Use K2Compiler via JvmFirPipeline to support Kotlin v2#6338

Closed
Crustack wants to merge 2 commits intoopenrewrite:mainfrom
Crustack:feat/kotlin-v2
Closed

Use K2Compiler via JvmFirPipeline to support Kotlin v2#6338
Crustack wants to merge 2 commits intoopenrewrite:mainfrom
Crustack:feat/kotlin-v2

Conversation

@Crustack
Copy link
Copy Markdown
Contributor

@Crustack Crustack commented Nov 25, 2025

What's changed?

  • Update kotlin-compiler dependencies to 2.2.21
  • Implement JvmFirPipeline to use current K2 phased compiler API (with disabled fail on compile errors) to generate FirFiles
  • Update KotlinIrTypeMapping, IrTreeVisitor, KotlinTypeIrSignatureBuilder to be compilable, but they are not used atm
  • Update KotlinTypeMapping, KotlinTypeSignatureBuilder, PsiElementAssociations for new compiler dependency versions to be compilable
  • Check all rewrite-kotlin and rewrite-gradle tests still work and adjust KotlinTypeMapping, KotlinTypeSignatureBuilder, PsiElementAssociations if necessary
  • For synthetic source files the contents are pasted into a temp folder to provide compiler with actual file path

What's your motivation?

Anyone you would like to review specifically?

@shanman190
@jkschneider

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've read and applied the recipe conventions and best practices
  • I've used the IntelliJ IDEA auto-formatter on affected files

@Crustack Crustack marked this pull request as ready for review December 13, 2025 12:06
@Crustack
Copy link
Copy Markdown
Contributor Author

Crustack commented Dec 13, 2025

@timtebeek @shanman190 @jkschneider PR is now ready for proper review

FYI: I also tested adding support for properly compiling build.gradle.kts with Kotlin DSL, which works great and enables proper Kotlin support for many gradle recipes.
I will add another PR for it if/after this has been merged

Copy link
Copy Markdown
Member

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

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

Thanks for your continued efforts here @Crustack ! For the uninitiated (me) could you explain a bit about the what the FIR processing is / adds, and any trade offs as compared to what we had before, and impact on say Kotlin v1 support? That would mean we're better able to review this work, as it seems promising but it's a bit hard to say without more context.

Comment on lines +351 to +377
// TODO: Compiler Source File args need to be an actual file path therefore copying synthetic file to temp folder
public static String tempFile(ExecutionContext ctx, Input source, AtomicInteger idx) {
String fileName;
if ("openRewriteFile.kt".equals(source.getPath().toString())) {
fileName = "openRewriteFile" + idx.getAndIncrement() + ".kt";
} else if ("openRewriteFile.kts".equals(source.getPath().toString())) {
fileName = "openRewriteFile" + idx.getAndIncrement() + ".kts";
} else {
fileName = source.getPath().toString();
}
if(TEMP_SOURCE_DIR == null) {
try {
TEMP_SOURCE_DIR = Files.createTempDirectory("rewrite");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
addJvmClasspathRoot(compilerConfiguration, PathUtil.getResourcePathForClass(AnnotationTarget.class));
Path tempFile = TEMP_SOURCE_DIR.resolve(fileName);
try {
Files.createDirectories(tempFile.getParent());
Files.copy(source.getSource(ctx), tempFile, StandardCopyOption.REPLACE_EXISTING);
} catch (FileAlreadyExistsException ignored) {
} catch (IOException e) {
throw new RuntimeException(e);
}
return tempFile.toAbsolutePath().toString();
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Calling this out for my colleagues as creating files on disk might be a little different when it concerns the CLI / workers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was trying to use the WorkingDirectoryExecutionContextView's working directory to create these temp files (which is only necessary for synthetic temp files in Unit Tests), but executing:

WorkingDirectoryExecutionContextView.view(ctx).getWorkingDirectory()

In Unit Tests throws NullPointerException, because the context has no CURRENT_CYCLE` message. Not sure how to proceed on this.

Comment on lines +574 to +587
is IrSimpleType -> {
when (type.getPrimitiveType()) {
PrimitiveType.INT -> JavaType.Primitive.Int
PrimitiveType.BOOLEAN -> JavaType.Primitive.Boolean
PrimitiveType.BYTE -> JavaType.Primitive.Byte
PrimitiveType.CHAR -> JavaType.Primitive.Char
PrimitiveType.DOUBLE -> JavaType.Primitive.Double
PrimitiveType.FLOAT -> JavaType.Primitive.Float
PrimitiveType.LONG -> JavaType.Primitive.Long
PrimitiveType.SHORT -> JavaType.Primitive.Short
else -> when {
type.isStringClassType() -> JavaType.Primitive.String
type.isNothing() || type.isNullableNothing() -> JavaType.Primitive.None
else -> JavaType.Primitive.None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Love that you've thought to do this as well; it's been a bit of a sore point to me that some Spring migration method patterns failed to match because they were using Java primitives instead of Kotlin primitives.

@timtebeek
Copy link
Copy Markdown
Member

Thanks for your continued efforts here @Crustack ! For the uninitiated (me) could you explain a bit about the what the FIR processing is / adds, and any trade offs as compared to what we had before, and impact on say Kotlin v1 support? That would mean we're better able to review this work, as it seems promising but it's a bit hard to say without more context.

Not sure if you'd seen my earlier comment @Crustack , but it would help us better judge the scope & impact of the work done here, and how it compares to our support for Kotlin v1. Is v1 still supported with your changes for instance?

@Crustack
Copy link
Copy Markdown
Contributor Author

Crustack commented Jan 18, 2026

Not sure if you'd seen my earlier comment @Crustack , but it would help us better judge the scope & impact of the work done here, and how it compares to our support for Kotlin v1. Is v1 still supported with your changes for instance?

Hi @timtebeek , sorry for not responding earlier.
With the changes of this PR:

  • KotlinParser still uses PSI+FIR as before, but just with the newer Kotlin Compiler API
  • Uses the new K2 Compiler and supports Kotlin v2 (which was already attempted by Kotlin 2 #5963, Add support for Kotlin 2.x #5575)
  • All Kotlin Tests also pass for e.g. Kotlin v1.9
  • I also figured out how to utilize gradle Kotlin Script Templates with the new compiler API to better parse build.gradle.kts files and improve method/field matching for them (which I can submit in a future PR)
  • In a next step you could improve Kotlin parsing further by compiling to IR by adding the JvmFir2IrPipelinePhase to JvmFirPipeline (see JvmCliPipeline)

@timtebeek
Copy link
Copy Markdown
Member

Thanks again for your help here @Crustack ! Youl'll find some of the same changes you've suggested merged in this PR

Hope that has you going with 2.2 support for your use cases there!

@timtebeek timtebeek closed this Feb 18, 2026
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Feb 18, 2026
@Crustack
Copy link
Copy Markdown
Contributor Author

To be honest I'm a bit disappointed that over the course of 3 months this PR has not been actually reviewed and then to see an internal PR being created separately and merged immediately.
I would have gladly provided more info or respond to any given feedback.
I understand that internal contributions are generally preferred over outsiders', but since this took a lot of effort, I feel like I could have worked on something else instead if I knew there was no actual interest in it.
But, I will also admit that I should have probably reached out sooner on Slack, I just thought since there was no activity in #5963 and #5575 that it would be welcomed...

Thanks to @timtebeek for the initial feedback, and I'm glad to see K2 support being added

Have a nice week.

@Crustack Crustack deleted the feat/kotlin-v2 branch February 19, 2026 16:43
@timtebeek
Copy link
Copy Markdown
Member

Hi @Crustack ; understandable that you're disappointed to not see this explicitly evaluated in depth or merge;d know that it's never easy to decide which of competing PRs to continue from, as we had in this case. You might have noticed that in this case Marius' original work in #5575 was reflected in the commits. Know that your explorations did help validate the work done in the PR we merged, and was appreciated.

With larger efforts like these it's often hard to get alignment among all involved, and different folks have different styles of working through changes. Pulling work from different branches can than complicate matters when we're looking to get this delivered, but know that it's not our standard way of working.

Should you have any subsequent work you're considering do please reach out, via Slack or here, and I'll do my best to see things through where I can. In this case I myself wasn't confident enough to continue your work, as also evidenced by my earlier comments. But not that support for v2 is here, it should be easier to extend should you find room for improvement. 🙏🏻

@timtebeek
Copy link
Copy Markdown
Member

timtebeek commented Feb 22, 2026

@Crustack based on your hints above I figured explore Kotlin script templates for .kts; figured you'd be interested

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Support for Kotlin 2.2.0 Projects

2 participants