From cd4d47a9420ea405410929f91cc2a979dcef343e Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Wed, 20 Nov 2024 19:31:33 +0100 Subject: [PATCH 1/9] Add `AddAnnotationProcessor` recipe --- .../maven/AddAnnotationProcessor.java | 104 ++++++++++++++++ .../maven/AddAnnotationProcessorTest.java | 114 ++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java create mode 100644 rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java new file mode 100644 index 0000000000..7a09069d27 --- /dev/null +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -0,0 +1,104 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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.maven; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.xml.XPathMatcher; +import org.openrewrite.xml.XmlIsoVisitor; +import org.openrewrite.xml.tree.Xml; + +import java.util.Optional; + +import static org.openrewrite.xml.AddOrUpdateChild.addOrUpdateChild; + +@Value +@EqualsAndHashCode(callSuper = false) +public class AddAnnotationProcessor extends Recipe { + private static final XPathMatcher PLUGINS_MATCHER = new XPathMatcher("/project/build/plugins"); + private static final String MAVEN_COMPILER_PLUGIN_GROUP_ID = "org.apache.maven.plugins"; + private static final String MAVEN_COMPILER_PLUGIN_ARTIFACT_ID = "maven-compiler-plugin"; + + @Option(displayName = "Group", + description = "The first part of the coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add.", + example = "org.projectlombok") + String groupId; + + @Option(displayName = "Artifact", + description = "The second part of a coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add.", + example = "lombok-mapstruct-binding") + String artifactId; + + @Override + public String getDisplayName() { + return "Change Maven plugin configuration"; + } + + @Override + public String getDescription() { + return "Apply the specified configuration to a Maven plugin. Will not add the plugin if it does not already exist in the pom."; + } + + @Override + public TreeVisitor getVisitor() { + return new MavenVisitor() { + @Override + public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { + Xml.Tag plugins = (Xml.Tag) super.visitTag(tag, ctx); + if (PLUGINS_MATCHER.matches(getCursor())) { + Optional maybePlugin = plugins.getChildren().stream() + .filter(plugin -> + "plugin".equals(plugin.getName()) && + MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getChildValue("groupId").orElse(null)) && + MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getChildValue("artifactId").orElse(null)) + ) + .findAny(); + if (maybePlugin.isPresent()) { + Xml.Tag plugin = maybePlugin.get(); + plugin = new XmlIsoVisitor() { + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { + Xml.Tag tg = super.visitTag(tag, ctx); + if (tg.getName().equals("annotationProcessorPaths")) { + boolean found = false; + for (Xml.Tag child : tg.getChildren()) { + if (groupId.equals(child.getChildValue("groupId").orElse(null)) + && artifactId.equals(child.getChildValue("artifactId").orElse(null))) { + found = true; + } + } + if (!found) { + return tg.withContent( + ListUtils.concat(tg.getChildren(), + Xml.Tag.build(String.format("\n%s\n%s\n${version.mapstruct-lombok}\n", groupId, artifactId)))); + } + } + return tg; + } + }.visitTag(plugin, ctx); + plugins = addOrUpdateChild(plugins, plugin, getCursor()); + } + } + return autoFormat(plugins, ctx); + } + }; + } +} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java new file mode 100644 index 0000000000..fee8ed20c8 --- /dev/null +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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.maven; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.maven.Assertions.pomXml; + +class AddAnnotationProcessorTest implements RewriteTest { + + @DocumentExample + @Test + void addCommentToMavenDependency() { + rewriteRun( + spec -> spec.recipe(new AddAnnotationProcessor( + "org.projectlombok", + "lombok-mapstruct-binding" + )), + pomXml( + """ + + 4.0.0 + + com.mycompany.app + my-app + 1 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 9 + 9 + + + org.mapstruct + mapstruct-processor + ${version.mapstruct} + + + org.projectlombok + lombok + ${version.lombok} + + + + + + + + """, + """ + + 4.0.0 + + com.mycompany.app + my-app + 1 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 9 + 9 + + + org.mapstruct + mapstruct-processor + ${version.mapstruct} + + + org.projectlombok + lombok + ${version.lombok} + + + org.projectlombok + lombok-mapstruct-binding + ${version.mapstruct-lombok} + + + + + + + + """ + ) + ); + } + +} \ No newline at end of file From 616ed0db3a8e2110d5841231e92fd03175730fac Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Thu, 21 Nov 2024 15:27:37 +0100 Subject: [PATCH 2/9] Use `MavenPlugin` trait reverse arguments on equal check so no null checks are needed Adjust name and desc to match recipe --- .../maven/AddAnnotationProcessor.java | 35 ++++++++----------- .../openrewrite/maven/trait/MavenPlugin.java | 2 +- .../maven/AddAnnotationProcessorTest.java | 3 +- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index 7a09069d27..2b29d91785 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -22,14 +22,11 @@ import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; +import org.openrewrite.maven.trait.MavenPlugin; import org.openrewrite.xml.XPathMatcher; import org.openrewrite.xml.XmlIsoVisitor; import org.openrewrite.xml.tree.Xml; -import java.util.Optional; - -import static org.openrewrite.xml.AddOrUpdateChild.addOrUpdateChild; - @Value @EqualsAndHashCode(callSuper = false) public class AddAnnotationProcessor extends Recipe { @@ -49,12 +46,12 @@ public class AddAnnotationProcessor extends Recipe { @Override public String getDisplayName() { - return "Change Maven plugin configuration"; + return "Add an annotation processor to the maven compiler plugin"; } @Override public String getDescription() { - return "Apply the specified configuration to a Maven plugin. Will not add the plugin if it does not already exist in the pom."; + return "Add an annotation processor to the maven compiler plugin, will not do anything if it already exists."; } @Override @@ -63,21 +60,14 @@ public TreeVisitor getVisitor() { @Override public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag plugins = (Xml.Tag) super.visitTag(tag, ctx); - if (PLUGINS_MATCHER.matches(getCursor())) { - Optional maybePlugin = plugins.getChildren().stream() - .filter(plugin -> - "plugin".equals(plugin.getName()) && - MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getChildValue("groupId").orElse(null)) && - MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getChildValue("artifactId").orElse(null)) - ) - .findAny(); - if (maybePlugin.isPresent()) { - Xml.Tag plugin = maybePlugin.get(); - plugin = new XmlIsoVisitor() { + plugins = (Xml.Tag) new MavenPlugin.Matcher().asVisitor(plugin -> { + if (MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getGroupId()) + && MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getArtifactId())) { + return new XmlIsoVisitor() { @Override public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag tg = super.visitTag(tag, ctx); - if (tg.getName().equals("annotationProcessorPaths")) { + if ("annotationProcessorPaths".equals(tg.getName())) { boolean found = false; for (Xml.Tag child : tg.getChildren()) { if (groupId.equals(child.getChildValue("groupId").orElse(null)) @@ -93,11 +83,14 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { } return tg; } - }.visitTag(plugin, ctx); - plugins = addOrUpdateChild(plugins, plugin, getCursor()); + }.visitTag(plugin.getTree(), ctx); } + return plugin.getTree(); + }).visit(plugins, 0); + if (plugins != tag) { + plugins = autoFormat(plugins, ctx); } - return autoFormat(plugins, ctx); + return plugins; } }; } diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java index c4be15ef41..46b54299f2 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java @@ -59,7 +59,7 @@ public static class Matcher extends MavenTraitMatcher { private Optional getProperty(Cursor cursor, String property) { Xml.Tag tag = cursor.getValue(); - if (getResolutionResult(cursor).getPom().getProperties() != null) { + if (getResolutionResult(cursor) != null && getResolutionResult(cursor).getPom().getProperties() != null) { if (tag.getChildValue(property).isPresent() && tag.getChildValue(property).get().trim().startsWith("${")) { String propertyKey = tag.getChildValue(property).get().trim(); return Optional.ofNullable(getResolutionResult(cursor).getPom().getValue(propertyKey)); diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java index fee8ed20c8..de1fc1519c 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -110,5 +110,4 @@ void addCommentToMavenDependency() { ) ); } - -} \ No newline at end of file +} From 0c79452d3174845155776b9defda4bb9ca6ccf04 Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Thu, 21 Nov 2024 15:32:31 +0100 Subject: [PATCH 3/9] Add more test coverage and clearer test names --- .../maven/AddAnnotationProcessor.java | 7 ++- .../maven/AddAnnotationProcessorTest.java | 60 ++++++++++++++++++- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index 2b29d91785..32463fc8f7 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -44,6 +44,11 @@ public class AddAnnotationProcessor extends Recipe { example = "lombok-mapstruct-binding") String artifactId; + @Option(displayName = "Version", + description = "The third part of a coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add. Note that an exact version is expected", + example = "0.2.0") + String version; + @Override public String getDisplayName() { return "Add an annotation processor to the maven compiler plugin"; @@ -78,7 +83,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { if (!found) { return tg.withContent( ListUtils.concat(tg.getChildren(), - Xml.Tag.build(String.format("\n%s\n%s\n${version.mapstruct-lombok}\n", groupId, artifactId)))); + Xml.Tag.build(String.format("\n%s\n%s\n%s\n", groupId, artifactId, version)))); } } return tg; diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java index de1fc1519c..a6e5d10bc7 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -25,11 +25,12 @@ class AddAnnotationProcessorTest implements RewriteTest { @DocumentExample @Test - void addCommentToMavenDependency() { + void addAnnotationProcessor() { rewriteRun( spec -> spec.recipe(new AddAnnotationProcessor( "org.projectlombok", - "lombok-mapstruct-binding" + "lombok-mapstruct-binding", + "0.2.0" )), pomXml( """ @@ -98,7 +99,60 @@ void addCommentToMavenDependency() { org.projectlombok lombok-mapstruct-binding - ${version.mapstruct-lombok} + 0.2.0 + + + + + + + + """ + ) + ); + } + + @Test + void shouldNotAddProcessorAlreadyPresent() { + rewriteRun( + spec -> spec.recipe(new AddAnnotationProcessor( + "org.projectlombok", + "lombok-mapstruct-binding", + "0.2.0" + )), + pomXml( + """ + + 4.0.0 + + com.mycompany.app + my-app + 1 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 9 + 9 + + + org.mapstruct + mapstruct-processor + ${version.mapstruct} + + + org.projectlombok + lombok + ${version.lombok} + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 From 56e2c16c16e23a283186e0c4eeff7e0ee647d3b1 Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Thu, 21 Nov 2024 15:39:23 +0100 Subject: [PATCH 4/9] Lil cleanup --- .../maven/AddAnnotationProcessor.java | 2 +- .../maven/AddAnnotationProcessorTest.java | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index 32463fc8f7..f5f84249b9 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -56,7 +56,7 @@ public String getDisplayName() { @Override public String getDescription() { - return "Add an annotation processor to the maven compiler plugin, will not do anything if it already exists."; + return "Add an annotation processor to the maven compiler plugin. Will not do anything if it already exists. Also doesn't add anything when no other annotation processors are defined yet (Perhaps `ChangePluginConfiguration` can be used)."; } @Override diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java index a6e5d10bc7..071ada155f 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -36,7 +36,6 @@ void addAnnotationProcessor() { """ 4.0.0 - com.mycompany.app my-app 1 @@ -46,20 +45,15 @@ void addAnnotationProcessor() { org.apache.maven.plugins maven-compiler-plugin - 3.5.1 - 9 - 9 org.mapstruct mapstruct-processor - ${version.mapstruct} org.projectlombok lombok - ${version.lombok} @@ -71,7 +65,6 @@ void addAnnotationProcessor() { """ 4.0.0 - com.mycompany.app my-app 1 @@ -81,20 +74,15 @@ void addAnnotationProcessor() { org.apache.maven.plugins maven-compiler-plugin - 3.5.1 - 9 - 9 org.mapstruct mapstruct-processor - ${version.mapstruct} org.projectlombok lombok - ${version.lombok} org.projectlombok @@ -124,7 +112,6 @@ void shouldNotAddProcessorAlreadyPresent() { """ 4.0.0 - com.mycompany.app my-app 1 @@ -134,20 +121,15 @@ void shouldNotAddProcessorAlreadyPresent() { org.apache.maven.plugins maven-compiler-plugin - 3.5.1 - 9 - 9 org.mapstruct mapstruct-processor - ${version.mapstruct} org.projectlombok lombok - ${version.lombok} org.projectlombok From 4c98e8511c38822faf7c57b5e53af0c9e858d954 Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Thu, 21 Nov 2024 15:40:40 +0100 Subject: [PATCH 5/9] Lil cleanup --- .../java/org/openrewrite/maven/AddAnnotationProcessor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index f5f84249b9..010fc0f71f 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -23,14 +23,12 @@ import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; import org.openrewrite.maven.trait.MavenPlugin; -import org.openrewrite.xml.XPathMatcher; import org.openrewrite.xml.XmlIsoVisitor; import org.openrewrite.xml.tree.Xml; @Value @EqualsAndHashCode(callSuper = false) public class AddAnnotationProcessor extends Recipe { - private static final XPathMatcher PLUGINS_MATCHER = new XPathMatcher("/project/build/plugins"); private static final String MAVEN_COMPILER_PLUGIN_GROUP_ID = "org.apache.maven.plugins"; private static final String MAVEN_COMPILER_PLUGIN_ARTIFACT_ID = "maven-compiler-plugin"; @@ -91,7 +89,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { }.visitTag(plugin.getTree(), ctx); } return plugin.getTree(); - }).visit(plugins, 0); + }).visitNonNull(plugins, 0); if (plugins != tag) { plugins = autoFormat(plugins, ctx); } From 3a6bace01b6ad136cc8356d8bf81c4c32ce05b42 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 24 Nov 2024 23:53:20 +0100 Subject: [PATCH 6/9] Show handling of missing groupId and mismatched processor version --- .../org/openrewrite/maven/AddAnnotationProcessorTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java index 071ada155f..7c8bba9a32 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -43,7 +43,6 @@ void addAnnotationProcessor() { - org.apache.maven.plugins maven-compiler-plugin @@ -72,7 +71,6 @@ void addAnnotationProcessor() { - org.apache.maven.plugins maven-compiler-plugin @@ -134,7 +132,7 @@ void shouldNotAddProcessorAlreadyPresent() { org.projectlombok lombok-mapstruct-binding - 0.2.0 + 0.1.0 From c9946d10ac79deb4e08f9cf398238e3068f877e1 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 24 Nov 2024 23:54:03 +0100 Subject: [PATCH 7/9] Minor polish --- .../maven/AddAnnotationProcessor.java | 33 ++++++++++--------- .../openrewrite/maven/trait/MavenPlugin.java | 7 ++-- .../maven/trait/MavenTraitMatcher.java | 3 +- .../org/openrewrite/maven/trait/Traits.java | 0 4 files changed, 24 insertions(+), 19 deletions(-) rename rewrite-maven/src/{test => main}/java/org/openrewrite/maven/trait/Traits.java (100%) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index 010fc0f71f..fcbbe37755 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -22,10 +22,11 @@ import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; -import org.openrewrite.maven.trait.MavenPlugin; import org.openrewrite.xml.XmlIsoVisitor; import org.openrewrite.xml.tree.Xml; +import static org.openrewrite.maven.trait.Traits.mavenPlugin; + @Value @EqualsAndHashCode(callSuper = false) public class AddAnnotationProcessor extends Recipe { @@ -33,28 +34,31 @@ public class AddAnnotationProcessor extends Recipe { private static final String MAVEN_COMPILER_PLUGIN_ARTIFACT_ID = "maven-compiler-plugin"; @Option(displayName = "Group", - description = "The first part of the coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add.", + description = "The first part of the coordinate 'org.projectlombok:lombok-mapstruct-binding:0.2.0' of the processor to add.", example = "org.projectlombok") String groupId; @Option(displayName = "Artifact", - description = "The second part of a coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add.", + description = "The second part of a coordinate 'org.projectlombok:lombok-mapstruct-binding:0.2.0' of the processor to add.", example = "lombok-mapstruct-binding") String artifactId; @Option(displayName = "Version", - description = "The third part of a coordinate 'org.openrewrite.maven:rewrite-maven-plugin:VERSION' of the processor to add. Note that an exact version is expected", + description = "The third part of a coordinate 'org.projectlombok:lombok-mapstruct-binding:0.2.0' of the processor to add. " + + "Note that an exact version is expected", example = "0.2.0") String version; @Override public String getDisplayName() { - return "Add an annotation processor to the maven compiler plugin"; + return "Add an annotation processor to `maven-compiler-plugin`"; } @Override public String getDescription() { - return "Add an annotation processor to the maven compiler plugin. Will not do anything if it already exists. Also doesn't add anything when no other annotation processors are defined yet (Perhaps `ChangePluginConfiguration` can be used)."; + return "Add an annotation processor to the maven compiler plugin. Will not do anything if it already exists. " + + "Also doesn't add anything when no other annotation processors are defined yet. " + + "(Perhaps `ChangePluginConfiguration` can be used)."; } @Override @@ -63,7 +67,7 @@ public TreeVisitor getVisitor() { @Override public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag plugins = (Xml.Tag) super.visitTag(tag, ctx); - plugins = (Xml.Tag) new MavenPlugin.Matcher().asVisitor(plugin -> { + plugins = (Xml.Tag) mavenPlugin().asVisitor(plugin -> { if (MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getGroupId()) && MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getArtifactId())) { return new XmlIsoVisitor() { @@ -71,18 +75,15 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag tg = super.visitTag(tag, ctx); if ("annotationProcessorPaths".equals(tg.getName())) { - boolean found = false; for (Xml.Tag child : tg.getChildren()) { - if (groupId.equals(child.getChildValue("groupId").orElse(null)) - && artifactId.equals(child.getChildValue("artifactId").orElse(null))) { - found = true; + if (groupId.equals(child.getChildValue("groupId").orElse(null)) && + artifactId.equals(child.getChildValue("artifactId").orElse(null))) { + return tg; } } - if (!found) { - return tg.withContent( - ListUtils.concat(tg.getChildren(), - Xml.Tag.build(String.format("\n%s\n%s\n%s\n", groupId, artifactId, version)))); - } + return tg.withContent(ListUtils.concat(tg.getChildren(), Xml.Tag.build(String.format( + "\n%s\n%s\n%s\n", + groupId, artifactId, version)))); } return tg; } diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java index 46b54299f2..7b618cd750 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenPlugin.java @@ -18,6 +18,7 @@ import lombok.Value; import org.jspecify.annotations.Nullable; import org.openrewrite.Cursor; +import org.openrewrite.maven.tree.MavenResolutionResult; import org.openrewrite.trait.Trait; import org.openrewrite.xml.XPathMatcher; import org.openrewrite.xml.tree.Xml; @@ -29,6 +30,7 @@ public class MavenPlugin implements Trait { static final XPathMatcher PLUGIN_MATCHER = new XPathMatcher("//plugins/plugin"); Cursor cursor; + String groupId; @Nullable @@ -59,10 +61,11 @@ public static class Matcher extends MavenTraitMatcher { private Optional getProperty(Cursor cursor, String property) { Xml.Tag tag = cursor.getValue(); - if (getResolutionResult(cursor) != null && getResolutionResult(cursor).getPom().getProperties() != null) { + MavenResolutionResult resolutionResult = getResolutionResult(cursor); + if (resolutionResult != null && resolutionResult.getPom().getProperties() != null) { if (tag.getChildValue(property).isPresent() && tag.getChildValue(property).get().trim().startsWith("${")) { String propertyKey = tag.getChildValue(property).get().trim(); - return Optional.ofNullable(getResolutionResult(cursor).getPom().getValue(propertyKey)); + return Optional.ofNullable(resolutionResult.getPom().getValue(propertyKey)); } } return tag.getChildValue(property); diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenTraitMatcher.java b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenTraitMatcher.java index 09dce8228d..ff91e91b56 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenTraitMatcher.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/MavenTraitMatcher.java @@ -15,6 +15,7 @@ */ package org.openrewrite.maven.trait; +import org.jspecify.annotations.Nullable; import org.openrewrite.Cursor; import org.openrewrite.SourceFile; import org.openrewrite.maven.MavenVisitor; @@ -27,7 +28,7 @@ public abstract class MavenTraitMatcher> extends SimpleTraitMatcher { - protected MavenResolutionResult getResolutionResult(Cursor cursor) { + protected @Nullable MavenResolutionResult getResolutionResult(Cursor cursor) { AtomicReference mrr = new AtomicReference<>(); new MavenVisitor() { @Override diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/trait/Traits.java b/rewrite-maven/src/main/java/org/openrewrite/maven/trait/Traits.java similarity index 100% rename from rewrite-maven/src/test/java/org/openrewrite/maven/trait/Traits.java rename to rewrite-maven/src/main/java/org/openrewrite/maven/trait/Traits.java From a8e93493754dbdc2c5eb77abdf0d4d4693bdc32e Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 24 Nov 2024 23:56:21 +0100 Subject: [PATCH 8/9] Apply suggestions from code review --- .../java/org/openrewrite/maven/AddAnnotationProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index fcbbe37755..b1ecce5fb7 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -68,8 +68,8 @@ public TreeVisitor getVisitor() { public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag plugins = (Xml.Tag) super.visitTag(tag, ctx); plugins = (Xml.Tag) mavenPlugin().asVisitor(plugin -> { - if (MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getGroupId()) - && MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getArtifactId())) { + if (MAVEN_COMPILER_PLUGIN_GROUP_ID.equals(plugin.getGroupId()) && + MAVEN_COMPILER_PLUGIN_ARTIFACT_ID.equals(plugin.getArtifactId())) { return new XmlIsoVisitor() { @Override public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { From 79cfe61d5dffa45f028f14c0381cd295a73e2ded Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Mon, 25 Nov 2024 16:40:32 +0100 Subject: [PATCH 9/9] Replace existing version if newer version is higher --- .../maven/AddAnnotationProcessor.java | 16 ++++++++- .../maven/AddAnnotationProcessorTest.java | 36 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java index b1ecce5fb7..fbc2644eb3 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddAnnotationProcessor.java @@ -22,9 +22,13 @@ import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; +import org.openrewrite.semver.Semver; +import org.openrewrite.semver.VersionComparator; import org.openrewrite.xml.XmlIsoVisitor; import org.openrewrite.xml.tree.Xml; +import java.util.List; + import static org.openrewrite.maven.trait.Traits.mavenPlugin; @Value @@ -75,9 +79,19 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { Xml.Tag tg = super.visitTag(tag, ctx); if ("annotationProcessorPaths".equals(tg.getName())) { - for (Xml.Tag child : tg.getChildren()) { + for (int i = 0; i < tg.getChildren().size(); i++) { + Xml.Tag child = tg.getChildren().get(i); if (groupId.equals(child.getChildValue("groupId").orElse(null)) && artifactId.equals(child.getChildValue("artifactId").orElse(null))) { + if (!version.equals(child.getChildValue("version").orElse(null))) { + String oldVersion = child.getChildValue("version").orElse(""); + VersionComparator comparator = Semver.validate(oldVersion, null).getValue(); + if (comparator.compare(version, oldVersion) > 0) { + List tags = tg.getChildren(); + tags.set(i, child.withChildValue("version", version)); + return tg.withContent(tags); + } + } return tg; } } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java index 7c8bba9a32..b164cb28f9 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddAnnotationProcessorTest.java @@ -99,7 +99,7 @@ void addAnnotationProcessor() { } @Test - void shouldNotAddProcessorAlreadyPresent() { + void shouldUpdateProcessorVersionAlreadyPresent() { rewriteRun( spec -> spec.recipe(new AddAnnotationProcessor( "org.projectlombok", @@ -140,6 +140,40 @@ void shouldNotAddProcessorAlreadyPresent() { + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.mapstruct + mapstruct-processor + + + org.projectlombok + lombok + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + + + + """ ) );