Add recipe to extract complex explicit constructor invocation arguments (JEP 513) - #1135
Merged
Conversation
Extracts complex `super(..)` arguments (method invocations and object creations) into local variables declared right before the `super(..)` call, now that JEP 513 permits statements before the explicit constructor invocation. The transformation is strictly behavior preserving: argument expressions already evaluate before the super constructor body, and a super argument can never reference the instance under construction. Arguments are extracted in their original left-to-right order; trivial side-effect-free arguments (literals and local/parameter references) are left in place.
The recipe handles both super(..) and this(..) explicit constructor invocations, so the name now reflects the JLS umbrella term rather than only the super case.
ExtractSuperConstructorArgument recipe for JEP 513The argument-replacement visitor descended into nested/local classes and rewrote their super(..)/this(..) calls with the outer constructor's argument list. Guard against descending into nested class declarations. Also move ExtractExplicitConstructorInvocationArguments out of the default UpgradeToJava25 upgrade and into JavaBestPractices, since it restyles already-valid code rather than migrating it. Add tests for the nested-class case, varargs bail, statements before super, static-field extraction, and name-collision avoidance.
mergify Bot
added a commit
to robfrank/linklift
that referenced
this pull request
Jul 17, 2026
…37.0 to 3.40.0 [skip ci] Bumps [org.openrewrite.recipe:rewrite-migrate-java](https://github.com/openrewrite/rewrite-migrate-java) from 3.37.0 to 3.40.0. Release notes *Sourced from [org.openrewrite.recipe:rewrite-migrate-java's releases](https://github.com/openrewrite/rewrite-migrate-java/releases).* > 3.40.0 > ------ > > What's Changed > -------------- > > * Keep `\t` and `\f` escapes in UseTextBlocks to avoid incidental whitespace stripping by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1160](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1160) > * Skip UseEnumSetOf empty conversion for static fields to avoid circular class-init ([#1157](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1157)) by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1161](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1161) > * Skip `UseMapOf` for `LinkedHashMap`/`TreeMap` in the prose `put()` form ([#1163](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1163)) by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1165](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1165) > * Skip AddMockitoJavaAgentToMavenSurefirePlugin when agent already configured in build/plugins by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1166](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1166) > * Add RedundantUtf8Charset recipe to drop redundant UTF-8 from Files calls by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1167](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1167) > * Fix Jakarta EE 10 web.xml migration by [`@sakshichitnis27`](https://github.com/sakshichitnis27) in [openrewrite/rewrite-migrate-java#1159](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1159) > > New Contributors > ---------------- > > * [`@sakshichitnis27`](https://github.com/sakshichitnis27) made their first contribution in [openrewrite/rewrite-migrate-java#1159](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1159) > > **Full Changelog**: <openrewrite/rewrite-migrate-java@v3.39.0...v3.40.0> > > 3.39.0 > ------ > > What's Changed > -------------- > > * Make ExtractExplicitConstructorInvocationArguments templates context-free by [`@knutwannheden`](https://github.com/knutwannheden) in [openrewrite/rewrite-migrate-java#1140](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1140) > * Convert Javadoc `<br>` tags to Markdown line breaks by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1142](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1142) > * Preserve angle brackets when converting `@param <T>` to Markdown by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1141](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1141) > * Fix JavadocToMarkdown's handling of varargs and JDKs newer than the bytecode source/target compatibility by [`@sambsnyd`](https://github.com/sambsnyd) in [openrewrite/rewrite-migrate-java#1143](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1143) > * Move ReplaceUnusedVariablesWithUnderscore to Java best practices by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1144](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1144) > * Extend Use{List,Set,Map}Of to recognise prose-statement chains by [`@steve-aom-elliott`](https://github.com/steve-aom-elliott) in [openrewrite/rewrite-migrate-java#1145](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1145) > * Skip `UseMapOf` when the anonymous `HashMap` is assigned to a concrete `HashMap` variable by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1149](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1149) > * Fix jakarta.enterprise.concurrent-api version for EE9 and EE10 by [`@evie-lau`](https://github.com/evie-lau) in [openrewrite/rewrite-migrate-java#1152](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1152) > * Add recipe to replace jakarta jws-api with ws-api in EE10 by [`@evie-lau`](https://github.com/evie-lau) in [openrewrite/rewrite-migrate-java#1151](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1151) > * Upgrade maven-ejb-plugin alongside jakarta.ejb-api by [`@evie-lau`](https://github.com/evie-lau) in [openrewrite/rewrite-migrate-java#1155](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1155) > * Upgrade maven-ear-plugin for ee9 and ee11 by [`@evie-lau`](https://github.com/evie-lau) in [openrewrite/rewrite-migrate-java#1156](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1156) > > **Full Changelog**: <openrewrite/rewrite-migrate-java@v3.38.0...v3.39.0> > > v3.38.0 > ------- > > What's Changed > -------------- > > * use . instead # for FQN link in Markdown javadoc by [`@barbulescu`](https://github.com/barbulescu) in [openrewrite/rewrite-migrate-java#1134](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1134) > * Bump maven-pmd-plugin to 3.28.x for Java 25 support by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1136](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1136) > * Explain why Kotlin modules are capped at Java 24 during Java 25 migration by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1137](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1137) > * Preserve `@{argLine}` in AddSurefireFailsafeArgLine for JaCoCo coverage by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1138](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1138) > * Add recipe to extract complex explicit constructor invocation arguments (JEP 513) by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1135](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1135) > * Bump Kotlin 2.0-2.2 to 2.3 so Kotlin modules can reach Java 25 by [`@timtebeek`](https://github.com/timtebeek) in [openrewrite/rewrite-migrate-java#1139](https://redirect.github.com/openrewrite/rewrite-migrate-java/pull/1139) > > **Full Changelog**: <openrewrite/rewrite-migrate-java@v3.37.0...v3.38.0> Commits * [`6584812`](openrewrite/rewrite-migrate-java@6584812) Fix Jakarta EE 10 web.xml migration ([#1159](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1159)) * [`3d0ad8f`](openrewrite/rewrite-migrate-java@3d0ad8f) OpenRewrite recipe best practices * [`76925b9`](openrewrite/rewrite-migrate-java@76925b9) Add RedundantUtf8Charset recipe to drop redundant UTF-8 from Files calls ([#1167](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1167)) * [`c0d0f67`](openrewrite/rewrite-migrate-java@c0d0f67) Skip AddMockitoJavaAgentToMavenSurefirePlugin when agent already configured i... * [`12386c8`](openrewrite/rewrite-migrate-java@12386c8) Skip UseMapOf for LinkedHashMap/TreeMap in prose put-statement form ([#1163](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1163)) (... * [`ee2f4c4`](openrewrite/rewrite-migrate-java@ee2f4c4) OpenRewrite recipe best practices * [`5f18964`](openrewrite/rewrite-migrate-java@5f18964) Skip UseEnumSetOf empty conversion for static fields to avoid circular class-... * [`4cd2123`](openrewrite/rewrite-migrate-java@4cd2123) Keep \t and \f escapes in UseTextBlocks to avoid incidental whitespace stripp... * [`16e662d`](openrewrite/rewrite-migrate-java@16e662d) Upgrade maven-ear-plugin for ee9 and ee11 ([#1156](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1156)) * [`b9f0360`](openrewrite/rewrite-migrate-java@b9f0360) Upgrade maven-ejb-plugin alongside jakarta.ejb-api ([#1155](https://redirect.github.com/openrewrite/rewrite-migrate-java/issues/1155)) * Additional commits viewable in [compare view](openrewrite/rewrite-migrate-java@v3.37.0...v3.40.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ExtractSuperConstructorArgumentrecipe (wired intoUpgradeToJava25, gated on Java 25+) that hoists complexsuper(..)arguments — method invocations and object creations — into local variables declared right before thesuper(..)call, made possible by JEP 513. The transformation is strictly behavior-preserving: super arguments already evaluate before the super constructor body and can never reference the instance under construction, so multiple arguments are extracted in their original left-to-right order while trivial side-effect-free arguments (literals and local/parameter references) are left in place. The wholesuper(..)is skipped when no argument does real work, when a parameter type isn't safely denotable (generics/arrays/type variables), or forthis(..)delegation. Relates to Move statements beforesuper(..)in Java constructor #733, scoped deliberately to the safe subset — statements that followsuper(..)are not moved, since reordering them relative to the super constructor's side effects could change behavior.Tests run under JDK 25 (
@EnabledForJreRange(min = JAVA_25)) covering single/multi-argument extraction, inline-safe siblings, and the negative cases.