Skip to content

feat(compose): Support the Kotlin 2.4 compiler plugin#1253

Merged
runningcode merged 7 commits into
mainfrom
claude/elegant-driscoll-fd35e1
Jun 4, 2026
Merged

feat(compose): Support the Kotlin 2.4 compiler plugin#1253
runningcode merged 7 commits into
mainfrom
claude/elegant-driscoll-fd35e1

Conversation

@runningcode

@runningcode runningcode commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What

  • Adds Kotlin 2.4 support to the Compose tracing compiler plugin. Kotlin 2.4 replaced ProjectExtensionDescriptor with ExtensionPointDescriptor as the IrGenerationExtension registration descriptor, so the single shared registration call threw IrGenerationExtension$Companion cannot be cast to ProjectExtensionDescriptor at runtime on the matrix. Registration is now delegated to per-version helpers (registerComposeTracing19/21/22/24), each compiled against its own compiler ABI, with SentryKotlinCompilerPlugin only dispatching via version-stable APIs. A new kotlin2400 variant (built against kotlin-compiler-embeddable:2.4.0) handles 2.4 IR generation.
  • Fixes a Compose instrumentation bug where chained modifiers (e.g. Modifier.fillMaxSize().padding()) were tagged multiple times. Since Kotlin 2.2 the unified IrFunction.parameters API also lists dispatch/extension/context receivers, so the receivers of chained calls got wrapped too. Wrapping is now restricted to IrParameterKind.Regular arguments. Affects the 2.2.0 and 2.4.0 variants; the 1.9.24 / 2.1.20 variants use the older valueParameters API and are unaffected.
  • Resolves three CI-matrix compile errors: toLowerCase/toUpperCase(Locale)lowercase/uppercase, and removes an invalid <Boolean?> type argument on the debug extension property (it stays Property<Boolean>).

Why

The nightly AGP/Gradle/Kotlin test matrix started exercising Kotlin 2.4 and failed at compiler-plugin registration, on top of the pre-existing deprecation and type-mismatch compile errors.

Closes #1257
Fixes Gradle-105

How

  • The compiler-plugin module's Kotlin Gradle Plugin is bumped to 2.3.21 (not 2.4): a 2.3 compiler can read 2.4.0 metadata to build the kotlin2400 variant, while keeping languageVersion at 1.9 and allowing a stable kotlin-compile-testing (0.12.1).
  • Each registration helper lives in its own source set, so only the runtime-selected one is loaded — keeping the version-specific descriptor types off every other Kotlin runtime's classpath.

Notes

  • The kotlin2400 variant is exercised end-to-end by the matrix's sample-app builds; the module's unit tests run on the 2.3 compiler and cover the fixed Extension22 path.
  • The chained-modifier over-wrapping was a latent bug in the released plugin on Kotlin 2.2+, not new to this PR.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 041b81b. Configure here.

* Default is disabled.
*/
val debug: Property<Boolean> = objects.property<Boolean?>(Boolean::class.java).convention(false)
val debug: Property<Boolean> = objects.property(Boolean::class.java).convention(false)

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.

small breaking API change

Comment thread gradle/libs.versions.toml Outdated
autoServiceAnnotatons = { group = "com.google.auto.service", name = "auto-service-annotations", version = "1.1.1" }
kotlinJunit = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit", version.ref = "kotlin" }
kotlinCompileTesting = { group = "dev.zacsweers.kctfork", name = "core", version = "0.7.1" }
# Pre-release: first kctfork that supports the Kotlin 2.4 compiler. Pin to a stable release once available.

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.

TODO remove this comment

// regular value parameters, otherwise modifier-receiver chains (e.g.
// Modifier.fillMaxSize().padding()) would each get their receiver wrapped as well.
if (
valueParameter.kind == IrParameterKind.Regular &&

@runningcode runningcode Jun 3, 2026

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.

Seems like this was an existing bug due to an existing bug in kctfork.

See this PR for this change independently: https://github.com/getsentry/sentry-android-gradle-plugin/pull/1254/changes

plugins {
alias(libs.plugins.kotlin) version "2.1.0"
alias(libs.plugins.kapt) version "2.1.0"
alias(libs.plugins.kotlin) version "2.3.21"

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.

Setting to 2.3.21 let's us keep our language version here at 1.9

import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames

// Modified duplicate of JetpackComposeTracingIrExtension22, compiled against 2.4.0

@runningcode runningcode Jun 3, 2026

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.

This was generated by claude and I don't have the full context on what to check here, it is mostly a copy.

@runningcode runningcode changed the title fix(build): Resolve Kotlin compile errors in CI matrix feat(compose): Support the Kotlin 2.4 compiler plugin Jun 3, 2026
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against cdd7724

Comment thread CHANGELOG.md
Comment thread CHANGELOG.md
get() = true

val pluginId: String = PLUGIN_ID
override val pluginId: String = PLUGIN_ID

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.

oh, I recall doing that #1046 (comment), but I guess now we're compiling against 2.3.x and it should be good?

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.

seems like that is true (since we now have KGP 2.3)

@romtsn

romtsn commented Jun 3, 2026

Copy link
Copy Markdown
Member

Great work!!

@linear-code

linear-code Bot commented Jun 4, 2026

Copy link
Copy Markdown

GRADLE-105

runningcode and others added 7 commits June 4, 2026 14:08
Replace deprecated toLowerCase/toUpperCase(Locale) with lowercase/
uppercase, and drop the invalid nullable Boolean type argument on the
debug property so it matches the declared Property<Boolean> type. These
were failing :plugin-build:compileKotlin on the CI matrix.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Kotlin 2.4 replaced ProjectExtensionDescriptor with ExtensionPointDescriptor
as the IrGenerationExtension registration descriptor, so the shared
registerExtension call (compiled against one compiler version) threw a
ClassCastException at runtime on a mismatched compiler.

Move the registration into per-version helpers compiled against their own
compiler ABI and have SentryKotlinCompilerPlugin only dispatch using
version-stable APIs, so a single artifact registers correctly on every
supported Kotlin version. Add a kotlin2400 variant built against 2.4.0 and
bump the module's Kotlin Gradle Plugin to 2.4.0 (language version 2.0), which
is required to read 2.4 compiler metadata.

The instrumentation tests are temporarily ignored because no stable
kotlin-compile-testing release supports the 2.4 compiler yet; the 2.4 path
remains covered by the sample-app builds in the test matrix.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Kotlin 2.4's unified parameter API lists dispatch/extension/context
receivers in IrFunction.parameters, so the 2.4 variant tagged the Modifier
receivers of chained calls (e.g. Modifier.fillMaxSize().padding()) in
addition to the composable's modifier argument, injecting three sentryTag
calls instead of one. Restrict wrapping to IrParameterKind.Regular
arguments.

Bump kotlin-compile-testing (kctfork) to 0.13.0-alpha01, the first release
that supports the Kotlin 2.4 compiler, and re-enable the instrumentation
tests that exercise this path.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Build the compiler-plugin module with Kotlin Gradle Plugin 2.3.21 instead
of 2.4.0 so the language version can stay at 1.9 and the tests can use a
stable kotlin-compile-testing (0.12.1); a 2.3 compiler can still read the
2.4.0 metadata needed to build the kotlin2400 variant.

Running the instrumentation tests on the 2.3 compiler surfaced that the
unified IrFunction.parameters API (Kotlin 2.2+) also lists dispatch,
extension and context receivers, so the 2.2.0 variant tagged the Modifier
receivers of chained calls (e.g. Modifier.fillMaxSize().padding()) in
addition to the composable's modifier argument. Restrict wrapping to
IrParameterKind.Regular arguments, matching the 2.4.0 variant. The 1.9.24
and 2.1.20 variants use the older valueParameters API and are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@runningcode
runningcode force-pushed the claude/elegant-driscoll-fd35e1 branch from d73287f to cdd7724 Compare June 4, 2026 12:12
@runningcode
runningcode merged commit caec0de into main Jun 4, 2026
23 checks passed
@runningcode
runningcode deleted the claude/elegant-driscoll-fd35e1 branch June 4, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kotlin 2.4.0 causes ClassCastException

2 participants