From dd1929895d6b0b3d9e61b43ea49ee9da868d9470 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 10:47:46 -0400 Subject: [PATCH 1/6] 1319: reproduce binding already configured as a Maven processor --- .../AddLombokMapstructBindingTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java index f4ed93ba5f..e2868e217f 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.openrewrite.DocumentExample; +import org.openrewrite.Issue; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; @@ -84,6 +85,67 @@ void doesNotDuplicateGradle() { ); } + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/1319") + @Test + void bindingAlreadyOnAnnotationProcessorPath() { + rewriteRun( + pomXml( + """ + + 4.0.0 + com.example + example-service + 1.0.0 + + + + org.projectlombok + lombok + 1.18.36 + provided + + + org.mapstruct + mapstruct + 1.6.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + + org.projectlombok + lombok + 1.18.36 + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + org.mapstruct + mapstruct-processor + 1.6.3 + + + + + + + + """ + ) + ); + } + @Test void addForMaven() { rewriteRun( From 76d5583d4b5fde6aa4186fa8054866c22ba4a91f Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 10:50:55 -0400 Subject: [PATCH 2/6] Clean regression fixture whitespace --- .../java/migrate/AddLombokMapstructBindingTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java index e2868e217f..ced40fcceb 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java @@ -97,7 +97,7 @@ void bindingAlreadyOnAnnotationProcessorPath() { com.example example-service 1.0.0 - + org.projectlombok @@ -111,7 +111,7 @@ void bindingAlreadyOnAnnotationProcessorPath() { 1.6.3 - + From 9477a62331ed44eae62d9decef107fb1eba567d8 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 10:54:31 -0400 Subject: [PATCH 3/6] 1319: respect module compiler paths before adding Lombok binding --- ...okMapstructBindingMavenDependencyOnly.java | 84 +++++++ .../META-INF/rewrite/java-version-17.yml | 17 -- ...pstructBindingMavenDependencyOnlyTest.java | 209 ++++++++++++++++++ .../AddLombokMapstructBindingTest.java | 133 +++++++++++ 4 files changed, 426 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java create mode 100644 src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java diff --git a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java new file mode 100644 index 0000000000..24aba60132 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java @@ -0,0 +1,84 @@ +/* + * Copyright 2026 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.maven.AddDependencyVisitor; +import org.openrewrite.maven.MavenIsoVisitor; +import org.openrewrite.maven.tree.Plugin; +import org.openrewrite.maven.tree.ResolvedPom; +import org.openrewrite.xml.tree.Xml; + +import java.util.List; + +@Value +@EqualsAndHashCode(callSuper = false) +public class AddLombokMapstructBindingMavenDependencyOnly extends Recipe { + String displayName = "Add `lombok-mapstruct-binding` dependency for Maven when both MapStruct and Lombok are used"; + + String description = "Add the `lombok-mapstruct-binding` Maven dependency when this module uses both Lombok and MapStruct " + + "and the binding is not already a dependency or configured on the compiler annotation processor path."; + + @Override + public TreeVisitor getVisitor() { + return new MavenIsoVisitor() { + @Override + public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { + if (getResolutionResult().findDependencies("org.projectlombok", "lombok", null).isEmpty() || + getResolutionResult().findDependencies("org.mapstruct", "mapstruct", null).isEmpty() || + !getResolutionResult().findDependencies("org.projectlombok", "lombok-mapstruct-binding", null).isEmpty()) { + return document; + } + ResolvedPom pom = getResolutionResult().getPom(); + if (hasBindingProcessor(pom, pom.getPlugins()) || hasBindingProcessor(pom, pom.getPluginManagement())) { + return document; + } + return (Xml.Document) new AddDependencyVisitor("org.projectlombok", "lombok-mapstruct-binding", "0.2.0", + null, null, null, null, null, null, null).visitNonNull(document, ctx); + } + + private boolean hasBindingProcessor(ResolvedPom pom, List plugins) { + for (Plugin plugin : plugins) { + if (!"org.apache.maven.plugins".equals(plugin.getGroupId()) || + !"maven-compiler-plugin".equals(plugin.getArtifactId()) || plugin.getConfiguration() == null) { + continue; + } + JsonNode paths = plugin.getConfiguration().path("annotationProcessorPaths").path("path"); + if (paths.isArray()) { + for (JsonNode path : paths) { + if (isBinding(pom, path)) { + return true; + } + } + } else if (isBinding(pom, paths)) { + return true; + } + } + return false; + } + + private boolean isBinding(ResolvedPom pom, JsonNode path) { + return "org.projectlombok".equals(pom.getValue(path.path("groupId").asText(""))) && + "lombok-mapstruct-binding".equals(pom.getValue(path.path("artifactId").asText(""))); + } + }; + } +} diff --git a/src/main/resources/META-INF/rewrite/java-version-17.yml b/src/main/resources/META-INF/rewrite/java-version-17.yml index 628b2c13d4..61c295a60f 100644 --- a/src/main/resources/META-INF/rewrite/java-version-17.yml +++ b/src/main/resources/META-INF/rewrite/java-version-17.yml @@ -379,20 +379,3 @@ recipeList: artifactId: lombok-mapstruct-binding version: 0.2.0 - org.openrewrite.java.migrate.AddMapstructAnnotationProcessorPath ---- -type: specs.openrewrite.org/v1beta/recipe -name: org.openrewrite.java.migrate.AddLombokMapstructBindingMavenDependencyOnly -displayName: Add `lombok-mapstruct-binding` dependency for Maven when both MapStruct and Lombok are used -description: >- - Add the `lombok-mapstruct-binding` Maven dependency when it does not already exist. Expects the caller to have checked - that both MapStruct and Lombok are used. -preconditions: - - org.openrewrite.java.dependencies.search.DoesNotIncludeDependency: - groupId: org.projectlombok - artifactId: lombok-mapstruct-binding - - org.openrewrite.Singleton -recipeList: - - org.openrewrite.maven.AddDependency: - groupId: org.projectlombok - artifactId: lombok-mapstruct-binding - version: 0.2.0 diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java new file mode 100644 index 0000000000..73d3bb5b6b --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java @@ -0,0 +1,209 @@ +/* + * Copyright 2025 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate; + +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.mavenProject; +import static org.openrewrite.maven.Assertions.pomXml; + +class AddLombokMapstructBindingMavenDependencyOnlyTest implements RewriteTest { + private static final String DEPENDENCIES = """ + + + org.projectlombok + lombok + 1.18.36 + provided + + + org.mapstruct + mapstruct + 1.6.3 + + + """; + private static final String BINDING = """ + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + """; + private static final String PROCESSOR = """ + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + """; + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new AddLombokMapstructBindingMavenDependencyOnly()); + } + + @Test + void legacyConfigurationAndIdempotency() { + rewriteRun( + spec -> spec.cycles(3).expectedCyclesThatMakeChanges(1), + pomXml(pom(DEPENDENCIES, ""), withBinding(pom(DEPENDENCIES, ""))) + ); + } + + @Test + void bindingMissingFromCompilerPaths() { + String before = pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR.replace("lombok-mapstruct-binding", "lombok"))); + rewriteRun(pomXml(before, withBinding(before))); + } + + @Test + void singleProcessorWithDefaultPluginGroup() { + rewriteRun(pomXml(pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR)))); + } + + @Test + void unrelatedPluginDoesNotSuppressDependency() { + String before = pom(DEPENDENCIES, plugin("maven-surefire-plugin", PROCESSOR)); + rewriteRun(pomXml(before, withBinding(before))); + } + + @Test + void unrelatedProcessorGroupDoesNotSuppressDependency() { + String before = pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR.replace("org.projectlombok", "com.example"))); + rewriteRun(pomXml(before, withBinding(before))); + } + + @Test + void existingDependencyKeepsScopeAndVersion() { + String dependencies = DEPENDENCIES.replace("", """ + + org.projectlombok + lombok-mapstruct-binding + ${binding.version} + provided + + """); + rewriteRun(pomXml(pom(dependencies, "").replace("", """ + + 0.2.0 + + """))); + } + + @Test + void unrelatedModuleDoesNotReceiveDependency() { + String unrelated = """ + + 4.0.0 + com.example + unrelated + 1 + + + org.projectlombok + lombok + 1.18.36 + + + + """; + rewriteRun( + mavenProject("configured", pomXml(pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR)))), + mavenProject("unrelated", pomXml(unrelated)), + mavenProject("missing", pomXml(pom(DEPENDENCIES, ""), withBinding(pom(DEPENDENCIES, "")))) + ); + } + + @Test + void inheritedCompilerConfiguration() { + String parent = pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR)) + .replace("app", "parent") + .replace("1", "1\n pom"); + rewriteRun( + mavenProject("parent", + pomXml(parent), + mavenProject("child", pomXml(""" + + 4.0.0 + + com.example + parent + 1 + + child + + """)) + ) + ); + } + + @Test + void managedCompilerConfiguration() { + String compiler = plugin("maven-compiler-plugin", PROCESSOR) + .replace("", "\n ") + .replace("", "\n "); + rewriteRun(pomXml(pom(DEPENDENCIES, compiler))); + } + + @Test + void processorCoordinatesUseProperties() { + String before = pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR + .replace("org.projectlombok", "${binding.group}") + .replace("lombok-mapstruct-binding", "${binding.artifact}"))) + .replace("", """ + + org.projectlombok + lombok-mapstruct-binding + + """); + rewriteRun(pomXml(before)); + } + + private static String pom(String dependencies, String build) { + return """ + + 4.0.0 + com.example + app + 1 + %s%s + """.formatted(dependencies.indent(2), build); + } + + private static String plugin(String artifact, String paths) { + return """ + + + + %s + 3.13.0 + + + %s + + + + + """.formatted(artifact, paths.indent(24)); + } + + private static String withBinding(String before) { + return before.replace(" ", BINDING.indent(2) + " "); + } +} diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java index ced40fcceb..c163d41086 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingTest.java @@ -146,6 +146,139 @@ void bindingAlreadyOnAnnotationProcessorPath() { ); } + @Test + void configuredModuleDoesNotSuppressOtherModules() { + rewriteRun( + spec -> spec.cycles(3).expectedCyclesThatMakeChanges(1), + mavenProject("configured", pomXml( + """ + + 4.0.0 + com.example + example-service + 1.0.0 + + + + org.projectlombok + lombok + 1.18.42 + provided + + + org.mapstruct + mapstruct + 1.6.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + + org.projectlombok + lombok + 1.18.42 + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + org.mapstruct + mapstruct-processor + 1.6.3 + + + + + + + + """ + )), + mavenProject("missing", pomXml( + """ + + com.mycompany.app + my-app + 1 + + + org.projectlombok + lombok + 1.18.42 + + + org.mapstruct + mapstruct + 1.6.3 + + + + """, + """ + + com.mycompany.app + my-app + 1 + + + org.projectlombok + lombok + 1.18.42 + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + org.mapstruct + mapstruct + 1.6.3 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + 1.18.42 + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + org.mapstruct + mapstruct-processor + 1.6.3 + + + + + + + + """ + )) + ); + } + @Test void addForMaven() { rewriteRun( From 843a4ac181b7a04be7bcbe55e8657669417b7448 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 10:59:03 -0400 Subject: [PATCH 4/6] 1319: retain compiler configuration after its null check --- .../AddLombokMapstructBindingMavenDependencyOnly.java | 8 ++++++-- .../AddLombokMapstructBindingMavenDependencyOnlyTest.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java index 24aba60132..273e6e1d62 100644 --- a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java +++ b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java @@ -58,10 +58,14 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { private boolean hasBindingProcessor(ResolvedPom pom, List plugins) { for (Plugin plugin : plugins) { if (!"org.apache.maven.plugins".equals(plugin.getGroupId()) || - !"maven-compiler-plugin".equals(plugin.getArtifactId()) || plugin.getConfiguration() == null) { + !"maven-compiler-plugin".equals(plugin.getArtifactId())) { continue; } - JsonNode paths = plugin.getConfiguration().path("annotationProcessorPaths").path("path"); + JsonNode configuration = plugin.getConfiguration(); + if (configuration == null) { + continue; + } + JsonNode paths = configuration.path("annotationProcessorPaths").path("path"); if (paths.isArray()) { for (JsonNode path : paths) { if (isBinding(pom, path)) { diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java index 73d3bb5b6b..46b9b12155 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 the original author or authors. + * Copyright 2026 the original author or authors. *

* Licensed under the Moderne Source Available License (the "License"); * you may not use this file except in compliance with the License. From 5b6f9296505e37b929ede39b05d1f52f53513532 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 11:08:14 -0400 Subject: [PATCH 5/6] 1319: honor child overrides of managed processor paths --- ...okMapstructBindingMavenDependencyOnly.java | 19 +++- ...pstructBindingMavenDependencyOnlyTest.java | 97 +++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java index 273e6e1d62..b60690a90b 100644 --- a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java +++ b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java @@ -48,13 +48,30 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { return document; } ResolvedPom pom = getResolutionResult().getPom(); - if (hasBindingProcessor(pom, pom.getPlugins()) || hasBindingProcessor(pom, pom.getPluginManagement())) { + if (hasBindingProcessor(pom, pom.getPlugins()) || + !overridesManagedProcessorPaths(pom.getPlugins()) && hasBindingProcessor(pom, pom.getPluginManagement())) { return document; } return (Xml.Document) new AddDependencyVisitor("org.projectlombok", "lombok-mapstruct-binding", "0.2.0", null, null, null, null, null, null, null).visitNonNull(document, ctx); } + private boolean overridesManagedProcessorPaths(List plugins) { + for (Plugin plugin : plugins) { + if (!"org.apache.maven.plugins".equals(plugin.getGroupId()) || + !"maven-compiler-plugin".equals(plugin.getArtifactId())) { + continue; + } + JsonNode configuration = plugin.getConfiguration(); + if (configuration != null && + ("override".equals(configuration.path("combine.self").asText()) || + "override".equals(configuration.path("annotationProcessorPaths").path("combine.self").asText()))) { + return true; + } + } + return false; + } + private boolean hasBindingProcessor(ResolvedPom pom, List plugins) { for (Plugin plugin : plugins) { if (!"org.apache.maven.plugins".equals(plugin.getGroupId()) || diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java index 46b9b12155..70253ad071 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java @@ -16,6 +16,8 @@ package org.openrewrite.java.migrate; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; @@ -161,6 +163,101 @@ void managedCompilerConfiguration() { rewriteRun(pomXml(pom(DEPENDENCIES, compiler))); } + @ParameterizedTest + @ValueSource(strings = {"annotationProcessorPaths", "configuration"}) + void explicitOverrideContainingBinding(String overriddenElement) { + rewriteRun(pomXml(pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR) + .replace("<" + overriddenElement + ">", "<" + overriddenElement + " combine.self=\"override\">")))); + } + + @Test + void managedProcessorInheritedByChildWithoutProcessorPaths() { + String managedCompiler = plugin("maven-compiler-plugin", PROCESSOR) + .replace("", "\n ") + .replace("", "\n "); + String parent = pom("", managedCompiler) + .replace("app", "parent") + .replace("1", "1\n pom"); + String child = pom(DEPENDENCIES, """ + + + + maven-compiler-plugin + + 17 + + + + + """) + .replace("com.example", """ + + com.example + parent + 1 + """); + rewriteRun( + mavenProject("parent", + pomXml(parent), + mavenProject("child", pomXml(child)) + ) + ); + } + + @ParameterizedTest + @ValueSource(strings = {"annotationProcessorPaths", "configuration"}) + void managedProcessorOverriddenInChild(String overriddenElement) { + String managedCompiler = plugin("maven-compiler-plugin", PROCESSOR) + .replace("", "\n ") + .replace("", "\n "); + String parent = pom("", managedCompiler) + .replace("app", "parent") + .replace("1", "1\n pom"); + String processors = PROCESSOR.replace("lombok-mapstruct-binding", "lombok").replace("0.2.0", "1.18.36") + + PROCESSOR.replace("org.projectlombok", "org.mapstruct").replace("lombok-mapstruct-binding", "mapstruct-processor").replace("0.2.0", "1.6.3"); + String child = pom(DEPENDENCIES, plugin("maven-compiler-plugin", processors) + .replace("<" + overriddenElement + ">", "<" + overriddenElement + " combine.self=\"override\">")) + .replace("com.example", """ + + com.example + parent + 1 + """); + rewriteRun( + mavenProject("parent", + pomXml(parent), + mavenProject("child", pomXml(child, withBinding(child))) + ) + ); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void compilerProcessorNotInheritedByChild(boolean managed) { + String compiler = plugin("maven-compiler-plugin", PROCESSOR) + .replace("3.13.0", "3.13.0\n false"); + if (managed) { + compiler = compiler.replace("", "\n ") + .replace("", "\n "); + } + String parent = pom("", compiler) + .replace("app", "parent") + .replace("1", "1\n pom"); + String child = pom(DEPENDENCIES, "") + .replace("com.example", """ + + com.example + parent + 1 + """); + rewriteRun( + mavenProject("parent", + pomXml(parent), + mavenProject("child", pomXml(child, withBinding(child))) + ) + ); + } + @Test void processorCoordinatesUseProperties() { String before = pom(DEPENDENCIES, plugin("maven-compiler-plugin", PROCESSOR From 7746c188088f7aeba832b0188462a686ff311790 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 25 Oct 2026 11:15:20 -0400 Subject: [PATCH 6/6] 1319: recognize locally declared non-inherited processors --- ...AddLombokMapstructBindingMavenDependencyOnly.java | 12 ++++++++++-- ...ombokMapstructBindingMavenDependencyOnlyTest.java | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java index b60690a90b..3c03858987 100644 --- a/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java +++ b/src/main/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnly.java @@ -21,6 +21,7 @@ import org.openrewrite.ExecutionContext; import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.ListUtils; import org.openrewrite.maven.AddDependencyVisitor; import org.openrewrite.maven.MavenIsoVisitor; import org.openrewrite.maven.tree.Plugin; @@ -48,14 +49,21 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { return document; } ResolvedPom pom = getResolutionResult().getPom(); - if (hasBindingProcessor(pom, pom.getPlugins()) || - !overridesManagedProcessorPaths(pom.getPlugins()) && hasBindingProcessor(pom, pom.getPluginManagement())) { + // The resolved model can omit even locally declared plugins with inherited=false. + List plugins = ListUtils.concatAll(pom.getPlugins(), nonInheritedPlugins(pom.getRequested().getPlugins())); + List managedPlugins = ListUtils.concatAll(pom.getPluginManagement(), nonInheritedPlugins(pom.getRequested().getPluginManagement())); + if (hasBindingProcessor(pom, plugins) || + !overridesManagedProcessorPaths(plugins) && hasBindingProcessor(pom, managedPlugins)) { return document; } return (Xml.Document) new AddDependencyVisitor("org.projectlombok", "lombok-mapstruct-binding", "0.2.0", null, null, null, null, null, null, null).visitNonNull(document, ctx); } + private List nonInheritedPlugins(List plugins) { + return ListUtils.map(plugins, plugin -> "false".equals(plugin.getInherited()) ? plugin : null); + } + private boolean overridesManagedProcessorPaths(List plugins) { for (Plugin plugin : plugins) { if (!"org.apache.maven.plugins".equals(plugin.getGroupId()) || diff --git a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java index 70253ad071..9b3b0e45f5 100644 --- a/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java +++ b/src/test/java/org/openrewrite/java/migrate/AddLombokMapstructBindingMavenDependencyOnlyTest.java @@ -231,6 +231,18 @@ void managedProcessorOverriddenInChild(String overriddenElement) { ); } + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void nonInheritedCompilerProcessorIsActiveInDeclaringPom(boolean managed) { + String compiler = plugin("maven-compiler-plugin", PROCESSOR) + .replace("3.13.0", "3.13.0\n false"); + if (managed) { + compiler = compiler.replace("", "\n ") + .replace("", "\n "); + } + rewriteRun(pomXml(pom(DEPENDENCIES, compiler))); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) void compilerProcessorNotInheritedByChild(boolean managed) {