Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.EqualsAndHashCode;
import lombok.Value;
import lombok.With;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.marker.Marker;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.maven.internal.MavenPomDownloader;
Expand Down Expand Up @@ -172,6 +174,9 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
@Override
public Xml.@Nullable Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
if (isDependencyTag()) {
if (tag.getMarkers().findFirst(Skip.class).isPresent()) {
return tag;
}
ResolvedDependency d = findDependency(tag);
if (d != null &&
matchesGroup(d) &&
Expand Down Expand Up @@ -409,4 +414,15 @@ private static class RemoveEmptyPluginsTags extends MavenIsoVisitor<ExecutionCon
return t;
}
}

/**
* A marker that can be placed on a Maven dependency tag to indicate that its explicit
* {@code <version>} should be retained, even when this recipe would otherwise remove it
* as redundant.
*/
@Value
@With
public static class Skip implements Marker {
UUID id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@
*/
package org.openrewrite.maven;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openrewrite.DocumentExample;
import org.openrewrite.Issue;
import org.openrewrite.Tree;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.test.SourceSpec;
import org.openrewrite.xml.tree.Xml;

import static java.util.Collections.singletonList;
import static org.openrewrite.java.Assertions.mavenProject;
import static org.openrewrite.maven.Assertions.pomXml;
import static org.openrewrite.test.RewriteTest.toRecipe;

class RemoveRedundantDependencyVersionsTest implements RewriteTest {

Expand Down Expand Up @@ -2282,4 +2286,192 @@ void exceptManagedDependencyShouldNotBeRemoved() {
)
);
}

@Nested
class SkipMarker {

@Test
void dependencyWithSkipMarkerKeepsVersion() {
String pom = """
<project>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies>
</project>
""";
rewriteRun(
spec -> spec.recipe(toRecipe(() -> new MavenIsoVisitor<>() {
@Override
public Xml.Tag visitTag(Xml.Tag tag, org.openrewrite.ExecutionContext ctx) {
Xml.Tag t = super.visitTag(tag, ctx);
if (isDependencyTag("com.google.guava", "guava") &&
!t.getMarkers().findFirst(RemoveRedundantDependencyVersions.Skip.class).isPresent()) {
t = t.withMarkers(t.getMarkers().add(new RemoveRedundantDependencyVersions.Skip(Tree.randomId())));
}
if (isProjectTag()) {
doAfterVisit(new RemoveRedundantDependencyVersions(null, null, null, null).getVisitor());
}
return t;
}
})),
pomXml(pom, pom)
);
}

@Test
void dependencyWithoutSkipMarkerHasVersionRemoved() {
rewriteRun(
pomXml(
"""
<project>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies>
</project>
""",
"""
<project>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>
"""
)
);
}

@Test
void skipMarkerOnlyAffectsMarkedDependency() {
rewriteRun(
spec -> spec.recipe(toRecipe(() -> new MavenIsoVisitor<>() {
@Override
public Xml.Tag visitTag(Xml.Tag tag, org.openrewrite.ExecutionContext ctx) {
Xml.Tag t = super.visitTag(tag, ctx);
if (isDependencyTag("com.google.guava", "guava") &&
!t.getMarkers().findFirst(RemoveRedundantDependencyVersions.Skip.class).isPresent()) {
t = t.withMarkers(t.getMarkers().add(new RemoveRedundantDependencyVersions.Skip(Tree.randomId())));
}
if (isProjectTag()) {
doAfterVisit(new RemoveRedundantDependencyVersions(null, null, null, null).getVisitor());
}
return t;
}
})),
pomXml(
"""
<project>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
</project>
""",
"""
<project>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>
"""
)
);
}
}
}