Skip to content

Skip incompatible registered mixins in TreeVisitorAdapter#7718

Closed
timtebeek wants to merge 1 commit into
mainfrom
tim/cross-language-mixin-filter
Closed

Skip incompatible registered mixins in TreeVisitorAdapter#7718
timtebeek wants to merge 1 commit into
mainfrom
tim/cross-language-mixin-filter

Conversation

@timtebeek

Copy link
Copy Markdown
Member

Summary

Filter registered mixins by language compatibility in TreeVisitorAdapter.discoverRegisteredMixin so that adapting a base visitor to one language's adaptTo doesn't pick up another language's mixin and crash.

Background

RemoveAnnotationKotlinMixin is registered for RemoveAnnotationVisitor via META-INF/rewrite/mixins/org.openrewrite.java.RemoveAnnotationVisitor. When RemoveAnnotationVisitor runs against a Groovy file, G.accept adapts it to GroovyVisitor — but discoverRegisteredMixin returned the Kotlin mixin unconditionally, and the assignability check at the top of adapt then 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 affects any recipe that uses RemoveAnnotation (or any other base visitor with a language-specific mixin registered) when it touches a Groovy / non-Kotlin source file. Surfaced via SpringBootVersionUpgradeTest.upgradeSpringCloudAwsVersion in rewrite-spring, which exercises this on a Gradle Groovy build script.

Fix

In discoverRegisteredMixin, skip entries whose class isn't a subtype of adaptTo rather than returning them. A registry file may list multiple language-specific mixins for the same base — the discovery loop now passes over incompatible ones and finds the matching one (or returns null so dispatch falls through to the base).

Test plan

  • New crossLanguageRegisteredMixinSkipped in TreeVisitorAdapterTest — fails without the fix with the exact IllegalArgumentException above, passes with it.
  • Existing TreeVisitorAdapterTest cases still pass.
  • End-to-end: published locally and re-ran the originally failing SpringBootVersionUpgradeTest.upgradeSpringCloudAwsVersion in rewrite-spring — now green.

A base visitor like `RemoveAnnotationVisitor` can have mixins
registered from multiple language modules — Kotlin's mixin extends
`KotlinIsoVisitor`, a Groovy mixin would extend `GroovyVisitor`,
etc. `discoverRegisteredMixin` returned the first registered entry
unconditionally; if its language didn't match `adaptTo`, `adapt`
then threw `Mixin ... is not assignable to ...`.

Concretely: adapting `RemoveAnnotationVisitor` to `GroovyVisitor`
(triggered by any Spring Boot upgrade recipe applied to a Gradle
Groovy build script) crashed because `RemoveAnnotationKotlinMixin`
was picked up.

Filter mixin entries by `adaptTo.isAssignableFrom(mixinClass)` so
the discovery loop can pass over Kotlin-only / Java-only / etc.
mixins and find the one that matches the current target — or
return `null` so dispatch falls through to the base visitor.
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite May 18, 2026
@timtebeek timtebeek marked this pull request as draft May 18, 2026 09:57
@timtebeek timtebeek requested a review from MBoegers May 18, 2026 09:59
@Jenson3210

Copy link
Copy Markdown
Contributor

Looks like we've both been working on the mixin downstream.

I'll leave it up to you to determine which is the best solution

@timtebeek

Copy link
Copy Markdown
Member Author

Thanks! Yours is more succinct; let's go for that one.

@timtebeek timtebeek closed this May 18, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite May 18, 2026
@timtebeek timtebeek deleted the tim/cross-language-mixin-filter branch May 18, 2026 10:56
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