Skip to content

Fix RemoveAnnotation crash on Groovy trees when rewrite-kotlin is on the classpath#7720

Merged
Jenson3210 merged 2 commits into
mainfrom
Jenson3210/fix-kotlin-mixin-groovy-adapt
May 18, 2026
Merged

Fix RemoveAnnotation crash on Groovy trees when rewrite-kotlin is on the classpath#7720
Jenson3210 merged 2 commits into
mainfrom
Jenson3210/fix-kotlin-mixin-groovy-adapt

Conversation

@Jenson3210

@Jenson3210 Jenson3210 commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

The registry is a shared namespace — multiple language modules can register a mixin for the same base visitor. But TreeVisitorAdapter.discoverRegisteredMixin returned the first entry it found without checking it was assignable to the requested adaptTo class. With both rewrite-groovy and rewrite-kotlin on the classpath (e.g. via rewrite-gradle, rewrite-spring, etc.), visiting a Groovy build.gradle did this:

  1. G.acceptv.adapt(GroovyVisitor.class)
  2. discoverRegisteredMixin returned RemoveAnnotationKotlinMixin (registered by rewrite-kotlin)
  3. adapt()'s assignability guard threw:
java.lang.IllegalArgumentException: Mixin org.openrewrite.kotlin.RemoveAnnotationKotlinMixin
is not assignable to org.openrewrite.groovy.GroovyVisitor; the mixin must extend (or be a
subtype of) the adaptTo class so that proxy generation can extend it.

This broke every downstream user that runs RemoveAnnotation (or any Java recipe that ends up adapting through G) against a Groovy build script — reported via SpringBootVersionUpgradeTest.upgradeVersionGradle in rewrite-spring.

Fix

Filter the registry entries inside discoverRegisteredMixin by adaptTo.isAssignableFrom(mixinClass) and continue past mismatched entries. A Kotlin mixin is silently ignored when adapting to GroovyVisitor (and vice versa) while still being picked up when the visit target really is a Kotlin tree.

  • rewrite-core/src/main/java/org/openrewrite/internal/TreeVisitorAdapter.java — skip cross-language mixin entries.
  • rewrite-gradle/src/test/java/org/openrewrite/gradle/RemoveAnnotationGradleTest.java — regression test: runs RemoveAnnotation against a Groovy build.gradle (in a module where both rewrite-groovy and rewrite-kotlin are on the classpath). Fails on main with the exact stack trace above, passes with the fix.

Test plan

  • New RemoveAnnotationGradleTest.doesNotApplyKotlinMixinToGroovyTree fails on main with the reported IllegalArgumentException.
  • Same test passes after the fix.
  • ./gradlew :rewrite-core:test :rewrite-kotlin:test :rewrite-groovy:test :rewrite-gradle:test (running locally; no Kotlin @file:OptIn removal coverage exists in rewrite-kotlin itself, so the Kotlin mixin path is only covered indirectly by the existing adapter-level tests).
  • Downstream repro SpringBootVersionUpgradeTest.upgradeVersionGradle in rewrite-spring should pass once this lands.

`META-INF/rewrite/mixins/<base-visitor-fqn>` is a shared registry: any
language module can contribute a mixin keyed by the same base visitor
FQN. When more than one language module is on the classpath (e.g.
`rewrite-groovy` + `rewrite-kotlin` together via `rewrite-gradle`),
`discoverRegisteredMixin` would return whichever entry it found first
regardless of the `adaptTo` target. That tripped the assignability
check in `adapt()` with:

    IllegalArgumentException: Mixin org.openrewrite.kotlin.RemoveAnnotationKotlinMixin
    is not assignable to org.openrewrite.groovy.GroovyVisitor

surfaced through `G.accept` -> `v.adapt(GroovyVisitor.class)` on any
Groovy `build.gradle` parsed by `GradleParser`.

Filter registry entries by `adaptTo.isAssignableFrom(mixinClass)` inside
the lookup itself so that a Kotlin mixin is silently skipped when
adapting to `GroovyVisitor` (and vice versa), while still being applied
when the visit target actually is a Kotlin tree.
@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite May 18, 2026
@Jenson3210 Jenson3210 merged commit 1d9d6a5 into main May 18, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite May 18, 2026
@Jenson3210 Jenson3210 deleted the Jenson3210/fix-kotlin-mixin-groovy-adapt branch May 18, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants