Skip to content

Commit a897423

Browse files
authored
Preserve @{argLine} in AddSurefireFailsafeArgLine for JaCoCo coverage (#1138)
* Preserve `@{argLine}` in AddSurefireFailsafeArgLine for JaCoCo coverage When writing or merging a surefire/failsafe `argLine`, prepend Surefire's `@{argLine}` late property reference so an agent injected into the `argLine` property by an earlier plugin (e.g. JaCoCo `prepare-agent`) is preserved rather than overwritten. The reference is not added when the existing `argLine` already references the `argLine` property (`@{argLine}`/`${argLine}`). * Regenerate recipes.csv for updated AddSurefireFailsafeArgLine description
1 parent 5cb24ac commit a897423

4 files changed

Lines changed: 149 additions & 16 deletions

File tree

src/main/java/org/openrewrite/java/migrate/AddSurefireFailsafeArgLine.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ public class AddSurefireFailsafeArgLine extends Recipe {
4444
String displayName = "Add `argLine` to surefire and failsafe plugins";
4545

4646
String description = "Adds the specified arguments to the `argLine` configuration of the Maven Surefire and Failsafe plugins, " +
47-
"merging with any existing argLine value without duplicating arguments.";
47+
"merging with any existing argLine value without duplicating arguments. " +
48+
"The `@{argLine}` [late property reference](https://maven.apache.org/surefire/maven-surefire-plugin/faq.html) is prepended " +
49+
"so that an agent injected by another plugin during the build, such as the JaCoCo coverage agent from " +
50+
"`jacoco-maven-plugin:prepare-agent`, is preserved rather than overwritten. It is not added when the existing " +
51+
"`argLine` already references the `argLine` property.";
4852

4953
@Override
5054
public TreeVisitor<?, ExecutionContext> getVisitor() {
@@ -81,19 +85,24 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
8185
return t.withContent( ListUtils.map( (List<Content>) t.getContent(), c ->
8286
c == config ? updatedConfig : c ) );
8387
}
84-
Xml.Tag newArgLine = Xml.Tag.build( "<argLine>" + argLine + "</argLine>" );
88+
Xml.Tag newArgLine = Xml.Tag.build( "<argLine>" + newArgLineValue() + "</argLine>" );
8589
Xml.Tag updatedConfig = config.withContent(
8690
ListUtils.concat( newArgLine, (List<Content>) config.getContent() ) );
8791
t = t.withContent( ListUtils.map( (List<Content>) t.getContent(), c ->
8892
c == config ? updatedConfig : c ) );
8993
return autoFormat( t, ctx );
9094
}
9195
Xml.Tag newConfig = Xml.Tag.build(
92-
"<configuration>\n<argLine>" + argLine + "</argLine>\n</configuration>" );
96+
"<configuration>\n<argLine>" + newArgLineValue() + "</argLine>\n</configuration>" );
9397
t = t.withContent( ListUtils.concat( (List<Content>) t.getContent(), newConfig ) );
9498
return autoFormat( t, ctx );
9599
}
96100

101+
// Value for a freshly created argLine: prepend the `@{argLine}` reference unless one is already present.
102+
private String newArgLineValue() {
103+
return argLine.contains("{argLine}") ? argLine : ARG_LINE_REFERENCE + " " + argLine;
104+
}
105+
97106
private boolean isPluginTag(Xml.Tag tag) {
98107
return "plugin".equals(tag.getName()) &&
99108
getCursor().getParentTreeCursor().getValue() instanceof Xml.Tag &&
@@ -104,6 +113,15 @@ private boolean isPluginTag(Xml.Tag tag) {
104113

105114
private static final Pattern ARG_PATTERN = Pattern.compile("(--add-opens\\s+\\S+|-\\S+(?:\\s+(?!-)\\S+)*)");
106115

116+
/**
117+
* Surefire's late property reference. Prepended to a newly written or merged {@code argLine} so that an
118+
* {@code -javaagent} injected into the {@code argLine} property by an earlier plugin in the build (most notably
119+
* the JaCoCo coverage agent set by {@code jacoco-maven-plugin:prepare-agent}) is preserved instead of overwritten.
120+
* Unlike {@code ${argLine}}, the {@code @{...}} form is resolved when Surefire executes rather than at POM
121+
* interpolation, so it picks up the value set during the build and resolves to an empty string when unset.
122+
*/
123+
static final String ARG_LINE_REFERENCE = "@{argLine}";
124+
107125
static String mergeArgLine(String existing, String toAdd) {
108126
// Parse compound args like "--add-opens module/pkg=target" as single units
109127
Set<String> existingArgs = parseArgs(existing);
@@ -118,10 +136,19 @@ static String mergeArgLine(String existing, String toAdd) {
118136
existingArgs.add(normalized);
119137
}
120138
}
121-
if (argsToAdd.isEmpty()) {
139+
// Prepend `@{argLine}` unless the existing value already references the `argLine` property (e.g. `${argLine}`)
140+
boolean needsArgLineReference = !existing.contains("{argLine}");
141+
if (argsToAdd.isEmpty() && !needsArgLineReference) {
122142
return existing;
123143
}
124-
StringBuilder result = new StringBuilder(existing);
144+
StringBuilder result = new StringBuilder();
145+
if (needsArgLineReference) {
146+
result.append(ARG_LINE_REFERENCE);
147+
if (!existing.isEmpty()) {
148+
result.append(' ');
149+
}
150+
}
151+
result.append(existing);
125152
for (String arg : argsToAdd) {
126153
result.append(' ').append(arg);
127154
}

src/main/resources/META-INF/rewrite/examples.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ examples:
240240
<artifactId>maven-surefire-plugin</artifactId>
241241
<version>3.5.2</version>
242242
<configuration>
243-
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED</argLine>
243+
<argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED</argLine>
244244
</configuration>
245245
</plugin>
246246
</plugins>

src/main/resources/META-INF/rewrite/recipes.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.A
1616
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.AddMockitoJavaAgentToMavenSurefirePlugin,Add Mockito Java Agent to Maven Surefire Plugin,Adds required configuration to specifically enable the Mockito/Bytebuddy Java agent in the Maven Surefire plugin for Java 21 compatibility.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
1717
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.AddStaticVariableOnProducerSessionBean,Adds `static` modifier to `@Produces` fields that are in session beans,"Ensures that the fields annotated with `@Produces` which is inside the session bean (`@Stateless`, `@Stateful`, or `@Singleton`) are declared `static`.",1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
1818
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.AddSuppressionForIllegalReflectionWarningsPlugin,Add maven jar plugin to suppress illegal reflection warnings,Adds a maven jar plugin that's configured to suppress Illegal Reflection Warnings.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""An exact version number, or node-style semver selector used to select the version number."",""example"":""29.X""}]",
19-
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.AddSurefireFailsafeArgLine,Add `argLine` to surefire and failsafe plugins,"Adds the specified arguments to the `argLine` configuration of the Maven Surefire and Failsafe plugins, merging with any existing argLine value without duplicating arguments.",1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""argLine"",""type"":""String"",""displayName"":""Arg line"",""description"":""The arguments to add to the surefire and failsafe plugin `argLine` configuration. Individual arguments are space-separated. Arguments already present in the existing argLine are not duplicated."",""example"":""--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED"",""required"":true}]",
19+
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.AddSurefireFailsafeArgLine,Add `argLine` to surefire and failsafe plugins,"Adds the specified arguments to the `argLine` configuration of the Maven Surefire and Failsafe plugins, merging with any existing argLine value without duplicating arguments. The `@{argLine}` [late property reference](https://maven.apache.org/surefire/maven-surefire-plugin/faq.html) is prepended so that an agent injected by another plugin during the build, such as the JaCoCo coverage agent from `jacoco-maven-plugin:prepare-agent`, is preserved rather than overwritten. It is not added when the existing `argLine` already references the `argLine` property.",1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""argLine"",""type"":""String"",""displayName"":""Arg line"",""description"":""The arguments to add to the surefire and failsafe plugin `argLine` configuration. Individual arguments are space-separated. Arguments already present in the existing argLine are not duplicated."",""example"":""--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED"",""required"":true}]",
2020
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.ArrayStoreExceptionToTypeNotPresentException,Catch `TypeNotPresentException` thrown by `Class.getAnnotation()`,Replace catch blocks for `ArrayStoreException` around `Class.getAnnotation()` with `TypeNotPresentException` to ensure compatibility with Java 11+.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
2121
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.BeanDiscovery,Behavior change to bean discovery in modules with `beans.xml` file with no version specified,Alters beans with missing version attribute to include this attribute as well as the bean-discovery-mode="all" attribute to maintain an explicit bean archive.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
2222
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.BeansXmlNamespace,Change `beans.xml` `schemaLocation` to match XML namespace,Set the `schemaLocation` that corresponds to the `xmlns` set in `beans.xml` files.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,

0 commit comments

Comments
 (0)