diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactId.java b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactId.java index c0cb645d7c0..905864d2e93 100755 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactId.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactId.java @@ -94,12 +94,22 @@ public class ChangeDependencyGroupIdAndArtifactId extends Recipe { @Nullable Boolean changeManagedDependency; + @Option(displayName = "Change property version name", + description = "Allows property version name to be changed to best practice naming convention. The default for this flag is `false`.", + required = false) + @Nullable + Boolean changePropertyVersionName; + public ChangeDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, @Nullable String newGroupId, @Nullable String newArtifactId, @Nullable String newVersion, @Nullable String versionPattern) { - this(oldGroupId, oldArtifactId, newGroupId, newArtifactId, newVersion, versionPattern, false, true); + this(oldGroupId, oldArtifactId, newGroupId, newArtifactId, newVersion, versionPattern, false, true, false); } - @JsonCreator public ChangeDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, @Nullable String newGroupId, @Nullable String newArtifactId, @Nullable String newVersion, @Nullable String versionPattern, @Nullable Boolean overrideManagedVersion, @Nullable Boolean changeManagedDependency) { + this(oldGroupId, oldArtifactId, newGroupId, newArtifactId, newVersion, versionPattern, overrideManagedVersion, changeManagedDependency, false); + } + + @JsonCreator + public ChangeDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, @Nullable String newGroupId, @Nullable String newArtifactId, @Nullable String newVersion, @Nullable String versionPattern, @Nullable Boolean overrideManagedVersion, @Nullable Boolean changeManagedDependency, @Nullable Boolean changePropertyVersionName) { this.oldGroupId = oldGroupId; this.oldArtifactId = oldArtifactId; this.newGroupId = newGroupId; @@ -108,6 +118,7 @@ public ChangeDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifac this.versionPattern = versionPattern; this.overrideManagedVersion = overrideManagedVersion; this.changeManagedDependency = changeManagedDependency; + this.changePropertyVersionName = changePropertyVersionName != null && changePropertyVersionName; // False by default } @Override @@ -156,13 +167,13 @@ public TreeVisitor getVisitor() { @Override public Xml visitDocument(Xml.Document document, ExecutionContext ctx) { - // Any managed dependency change is unlikely to use the same version, so only update selectively. - if ((changeManagedDependency == null || changeManagedDependency) && newVersion != null || versionPattern != null) { + // Any managed dependency change is unlikely to use the same version, so only update selectively. If the new dependency is already managed, don't change the old dependency. It will be removed at the end. + if ((changeManagedDependency == null || changeManagedDependency) && newVersion != null && !isDependencyManaged(newGroupId, newArtifactId, newVersion)) { doAfterVisit(new ChangeManagedDependencyGroupIdAndArtifactId( oldGroupId, oldArtifactId, Optional.ofNullable(newGroupId).orElse(oldGroupId), Optional.ofNullable(newArtifactId).orElse(oldArtifactId), - newVersion, versionPattern).getVisitor()); + newVersion, versionPattern, changePropertyVersionName).getVisitor()); } return super.visitDocument(document, ctx); } @@ -202,14 +213,22 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { if (!configuredToOverrideManageVersion && newDependencyManaged || (oldDependencyManaged && configuredToChangeManagedDependency)) { t = (Xml.Tag) new RemoveContentVisitor<>(versionTag.get(), false).visit(t, ctx); } else { - // Otherwise, change the version to the new value. - t = changeChildTagValue(t, "version", resolvedNewVersion, ctx); + doAfterVisit(new ChangeDependencyVersionValue(groupId, artifactId, newVersion, versionPattern, changePropertyVersionName, ChangeDependencyVersionValue.VersionLocation.DEPENDENCY.name()).getVisitor()); + + } + } else if (!(newDependencyManaged && configuredToChangeManagedDependency)) { + //If the Version not present and the new version is not managed and/or the changeManagedDependency Option is false. + List md = getResolutionResult().getPom().getDependencyManagement(); + if (configuredToOverrideManageVersion || ((!md.isEmpty() && md.get(0).getRequestedBom() != null) && !newDependencyManaged) || !configuredToChangeManagedDependency) { + //If the version is not present, add the version if we are explicitly overriding a managed version, if no managed version exists with no collection of dependencies or changeManageDependency is false. + Xml.Tag newVersionTag = Xml.Tag.build("" + resolvedNewVersion + ""); + //noinspection ConstantConditions + t = (Xml.Tag) new AddToTagVisitor(t, newVersionTag, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParent()); } - } else if (configuredToOverrideManageVersion || !newDependencyManaged) { - //If the version is not present, add the version if we are explicitly overriding a managed version or if no managed version exists. - Xml.Tag newVersionTag = Xml.Tag.build("" + resolvedNewVersion + ""); - //noinspection ConstantConditions - t = (Xml.Tag) new AddToTagVisitor(t, newVersionTag, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParent()); + + } else if (oldDependencyManaged){ + //If the version is not present and the new and old version are managed, remove the old dependency + doAfterVisit(new RemoveManagedDependency(oldGroupId,oldArtifactId, null).getVisitor()); } } catch (MavenDownloadingException e) { return e.warn(tag); @@ -243,6 +262,17 @@ private boolean isDependencyManaged(Scope scope, String groupId, String artifact return false; } + private boolean isDependencyManaged(String groupId, String artifactId, String version) { + + MavenResolutionResult result = getResolutionResult(); + for (ResolvedManagedDependency managedDependency : result.getPom().getDependencyManagement()) { + if (groupId.equals(managedDependency.getGroupId()) && artifactId.equals(managedDependency.getArtifactId()) && version.equals(managedDependency.getVersion())) { + return true; + } + } + return false; + } + @SuppressWarnings("ConstantConditions") private String resolveSemverVersion(ExecutionContext ctx, String groupId, String artifactId, @Nullable String currentVersion) throws MavenDownloadingException { if (versionComparator == null) { diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyVersionValue.java b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyVersionValue.java new file mode 100644 index 00000000000..5f56855184d --- /dev/null +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyVersionValue.java @@ -0,0 +1,290 @@ +/* + * Copyright 2022 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 com.fasterxml.jackson.annotation.JsonCreator; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.*; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.maven.table.MavenMetadataFailures; +import org.openrewrite.maven.tree.MavenMetadata; +import org.openrewrite.semver.Semver; +import org.openrewrite.semver.VersionComparator; +import org.openrewrite.xml.ChangeTagValueVisitor; +import org.openrewrite.xml.tree.Xml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static org.openrewrite.Validated.test; +import static org.openrewrite.internal.StringUtils.*; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ChangeDependencyVersionValue extends Recipe { + private static final Logger log = LoggerFactory.getLogger(ChangeDependencyVersionValue.class); + + @EqualsAndHashCode.Exclude + MavenMetadataFailures metadataFailures = new MavenMetadataFailures(this); + + // there are several implicitly defined version properties that we should never attempt to update + private static final Set implicitlyDefinedVersionProperties = new HashSet<>(Arrays.asList( + "${version}", "${project.version}", "${pom.version}", "${project.parent.version}" + )); + + public enum VersionLocation { + DEPENDENCY ("DEPENDENCY"), + MANAGED_DEPENDENCY ("MANAGED_DEPENDENCY"), + PLUGIN_DEPENDENCY ("PLUGIN_DEPENDENCY"); + + private final String name; + + VersionLocation(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } + } + + + @Option(displayName = "New groupId", + description = "The new groupId to use.", + example = "corp.internal.openrewrite.recipe") + String groupId; + + @Option(displayName = "New artifactId", + description = "The new artifactId to use.", + example = "rewrite-testing-frameworks") + String artifactId; + + @Option(displayName = "New version", + description = "The new version to use.", + example = "2.0.0", + required = false) + @Nullable + String newVersion; + + @Option(displayName = "Version pattern", + description = "Allows version selection to be extended beyond the original Node Semver semantics. So for example," + + "Setting 'version' to \"25-29\" can be paired with a metadata pattern of \"-jre\" to select Guava 29.0-jre", + example = "-jre", + required = false) + @Nullable + String versionPattern; + + @Option(displayName = "Change property version name", + description = "Allows property version name to be changed to best practice naming convention or what ever is in the newPropertyVersionName option. The default for this flag is `false`.", + required = false) + @Nullable + Boolean changePropertyVersionName; + + @Option(displayName = "New property version name", + description = "The new property version name used as property variable name. If it is set it will be changed. No need to set the changePropertyVersionName to true.", + example = "example.property.version", + required = false) + @Nullable + String newPropertyVersionName; + + @Option(displayName = "Declare the location where the dependency should be changed.", + description = "Changes dependency version right where you want it. The default is set to change it everywhere." + + "But you can also specifically target `DEPENDENCY`, `MANAGED_DEPENDENCY` or `PLUGIN_DEPENDENCY`." + + "It also doesn't matter if they are in a profile or not.", + example = "DEPENDENCY", + required = false) + @Nullable + ChangeDependencyVersionValue.VersionLocation versionLocation; + + public ChangeDependencyVersionValue(String groupId, String artifactId, @Nullable String newVersion, @Nullable String versionLocation) { + this(groupId, artifactId, newVersion, null, false, null, versionLocation); + } + + public ChangeDependencyVersionValue(String groupId, String artifactId, @Nullable String newVersion, @Nullable String versionPattern, @Nullable Boolean changePropertyVersionName, @Nullable String versionLocation) { + this(groupId, artifactId, newVersion, versionPattern, changePropertyVersionName, null, versionLocation); + } + + @JsonCreator + public ChangeDependencyVersionValue(String groupId, String artifactId, @Nullable String newVersion, @Nullable String versionPattern, @Nullable Boolean changePropertyVersionName, @Nullable String newPropertyVersionName, @Nullable String versionLocation) { + this.groupId = groupId; + this.artifactId = artifactId; + this.newVersion = newVersion; + this.versionPattern = versionPattern; + this.changePropertyVersionName = changePropertyVersionName != null && changePropertyVersionName; // False by default + this.newPropertyVersionName = newPropertyVersionName; + this.versionLocation = versionLocation != null ? VersionLocation.valueOf(versionLocation) : null; + } + + @Override + public Validated validate() { + Validated validated = super.validate(); + if (newVersion != null) { + validated = validated.and(Semver.validate(newVersion, versionPattern)); + } + validated = + validated.and(test( + "coordinates", + "newGroupId OR newArtifactId must be different from before", + this, + r -> { + boolean sameGroupId = isBlank(r.groupId); + boolean sameArtifactId = isBlank(r.artifactId); + return !(sameGroupId && sameArtifactId); + } + )); + return validated; + } + + @Override + public String getDisplayName() { + return "Change Maven dependency version"; + } + + @Override + public String getDescription() { + return "Change a Maven dependency version. Declare `groupId` and `artifactId` of the dependency in which the version should be changed. " + + "By adding `versionLocation`, a set of dependencies can be targeted such as managed Dependencies with `MANAGED_DEPENDENCY`."; + } + + @Override + public TreeVisitor getVisitor() { + return new MavenIsoVisitor() { + @Nullable + final VersionComparator versionComparator = newVersion != null ? Semver.validate(newVersion, versionPattern).getValue() : null; + @Nullable + private Collection availableVersions; + + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { + + Xml.Tag t = super.visitTag(tag, ctx); + + if (artifactId != null){ + if (matchesGlob(tag.getChildValue("groupId").orElse(null), groupId) && (artifactId == null || matchesGlob(tag.getChildValue("artifactId").orElse(null), artifactId))) { + String artifact = artifactId == null ? t.getChildValue("artifactId").orElse(null) : artifactId; + + if (newVersion != null){ + if (versionLocation == null){ + return changeVersion(t, ctx); + } + switch (Objects.requireNonNull(versionLocation)) { + case DEPENDENCY: + if (isDependencyTag() || PROFILE_DEPENDENCY_MATCHER.matches(getCursor())){ + return changeVersion(t, ctx); + } + break; + case MANAGED_DEPENDENCY: + if (isManagedDependencyTag() || PROFILE_MANAGED_DEPENDENCY_MATCHER.matches(getCursor())){ + return changeVersion(t, ctx); + } + break; + case PLUGIN_DEPENDENCY: + if (isPluginDependencyTag(groupId, artifact) || PROFILE_PLUGIN_DEPENDENCY_MATCHER.matches(getCursor())){ + return changeVersion(t, ctx); + } + break; + } + } + + } + } + + + return t; + } + + private Xml.Tag changeChildTagValue(Xml.Tag tag, String childTagName, String newValue, ExecutionContext ctx) { + Optional childTag = tag.getChild(childTagName); + if (childTag.isPresent() && !newValue.equals(childTag.get().getValue().orElse(null))) { + tag = (Xml.Tag) new ChangeTagValueVisitor<>(childTag.get(), newValue).visitNonNull(tag, ctx); + } + return tag; + } + + @SuppressWarnings("ConstantConditions") + private String resolveSemverVersion(ExecutionContext ctx, String groupId, String artifactId, @Nullable String currentVersion) throws MavenDownloadingException { + if (currentVersion.contains("$")) { + String propertyVariable = currentVersion.substring(2, currentVersion.length() - 1); + currentVersion = getResolutionResult().getPom().getProperties().get(propertyVariable); + } + + if (versionComparator == null) { + return newVersion; + } + String finalCurrentVersion = currentVersion != null ? currentVersion : newVersion; + if (availableVersions == null) { + availableVersions = new ArrayList<>(); + MavenMetadata mavenMetadata = metadataFailures.insertRows(ctx, () -> downloadMetadata(groupId, artifactId, ctx)); + for (String v : mavenMetadata.getVersioning().getVersions()) { + if (versionComparator.isValid(finalCurrentVersion, v)) { + availableVersions.add(v); + } + } + + } + return availableVersions.isEmpty() ? newVersion : Collections.max(availableVersions, versionComparator); + } + + public Xml.Tag changeVersion(Xml.Tag t, ExecutionContext ctx) { + + boolean changed = false; + if (newVersion != null) { + try { + Optional versionTag = t.getChild("version"); + if (versionTag.isPresent()) { + String version = versionTag.get().getValue().orElse(null); + String resolvedNewVersion = resolveSemverVersion(ctx, groupId, artifactId == null ? t.getChildValue("artifactId").orElse(null) : artifactId, version); + if (Objects.requireNonNull(version).contains("$")) { + String propertyVariable = version.substring(2, version.length() - 1); + String newPropertyVariable = propertyVariable; + if (!matchesGlob(getResolutionResult().getPom().getProperties().get(propertyVariable), resolvedNewVersion)) { + doAfterVisit(new ChangePropertyValue(newPropertyVariable, resolvedNewVersion, false, false).getVisitor()); + changed = true; + } + newPropertyVariable = artifactId + ".version"; + if (newPropertyVersionName != null) { + newPropertyVariable = newPropertyVersionName; + } + if (!getResolutionResult().getPom().getProperties().containsKey(newPropertyVariable) && (Boolean.TRUE.equals(changePropertyVersionName) || newPropertyVersionName != null)) { + doAfterVisit(new RenamePropertyKey(propertyVariable, newPropertyVariable).getVisitor()); + t = changeChildTagValue(t, "version", "${" + newPropertyVariable + "}", ctx); + changed = true; + } + } else { + if (!matchesGlob(t.getChildValue("version").orElse(null), resolvedNewVersion)){ + t = changeChildTagValue(t, "version", resolvedNewVersion, ctx); + changed = true; + } + } + + } + + } catch (MavenDownloadingException e) { + return e.warn(t); + } + } + if (changed) { + maybeUpdateModel(); + } + + return t; + } + }; + } +} diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactId.java b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactId.java index cc7204ea5a3..e0b47557607 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactId.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactId.java @@ -21,9 +21,7 @@ import org.jspecify.annotations.Nullable; import org.openrewrite.*; import org.openrewrite.maven.table.MavenMetadataFailures; -import org.openrewrite.maven.tree.MavenMetadata; import org.openrewrite.semver.Semver; -import org.openrewrite.semver.VersionComparator; import org.openrewrite.xml.ChangeTagValueVisitor; import org.openrewrite.xml.tree.Xml; @@ -72,29 +70,35 @@ public class ChangeManagedDependencyGroupIdAndArtifactId extends Recipe { @Option(displayName = "Version pattern", description = "Allows version selection to be extended beyond the original Node Semver semantics. So for example," + - "Setting 'version' to \"25-29\" can be paired with a metadata pattern of \"-jre\" to select Guava 29.0-jre", + "Setting 'version' to \"25-29\" can be paired with a metadata pattern of \"-jre\" to select Guava 29.0-jre", example = "-jre", required = false) @Nullable String versionPattern; + @Option(displayName = "Change property version name", + description = "Allows property version name to be changed to best practice naming convention. The default for this flag is `false`.", + required = false) + @Nullable + Boolean changePropertyVersionName; + public ChangeManagedDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, String newGroupId, String newArtifactId, @Nullable String newVersion) { - this.oldGroupId = oldGroupId; - this.oldArtifactId = oldArtifactId; - this.newGroupId = newGroupId; - this.newArtifactId = newArtifactId; - this.newVersion = newVersion; - this.versionPattern = null; + this(oldGroupId, oldArtifactId, newGroupId, newArtifactId, newVersion, null, false); } - @JsonCreator public ChangeManagedDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, String newGroupId, String newArtifactId, @Nullable String newVersion, @Nullable String versionPattern) { + this(oldGroupId, oldArtifactId, newGroupId, newArtifactId, newVersion, versionPattern, false); + } + + @JsonCreator + public ChangeManagedDependencyGroupIdAndArtifactId(String oldGroupId, String oldArtifactId, String newGroupId, String newArtifactId, @Nullable String newVersion, @Nullable String versionPattern, @Nullable Boolean changePropertyVersionName) { this.oldGroupId = oldGroupId; this.oldArtifactId = oldArtifactId; this.newGroupId = newGroupId; this.newArtifactId = newArtifactId; this.newVersion = newVersion; this.versionPattern = versionPattern; + this.changePropertyVersionName = changePropertyVersionName != null && changePropertyVersionName; // False by default } @Override @@ -130,10 +134,6 @@ public String getDescription() { @Override public TreeVisitor getVisitor() { return new MavenIsoVisitor() { - @Nullable - final VersionComparator versionComparator = newVersion != null ? Semver.validate(newVersion, versionPattern).getValue() : null; - @Nullable - private Collection availableVersions; @Override public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { @@ -151,18 +151,10 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { doAfterVisit(new ChangeTagValueVisitor<>(artifactIdTag.get(), newArtifactId)); changed = true; } - if (newVersion != null) { - try { - Optional versionTag = t.getChild("version"); - - if (versionTag.isPresent()) { - String resolvedNewVersion = resolveSemverVersion(ctx, newGroupId, newArtifactId, versionTag.get().getValue().orElse(null)); - t = (Xml.Tag) new ChangeTagValueVisitor<>(versionTag.get(), resolvedNewVersion).visitNonNull(t, 0, getCursor().getParentOrThrow()); - } - changed = true; - } catch(MavenDownloadingException e) { - return e.warn(t); - } + Optional versionTag = t.getChild("version"); + if (versionTag.isPresent() && newVersion != null && !newVersion.equals(versionTag.get().getValue().orElse(null))) { + doAfterVisit(new ChangeDependencyVersionValue(newGroupId, newArtifactId, newVersion, versionPattern, changePropertyVersionName, ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name()).getVisitor()); + changed = true; } if (changed) { maybeUpdateModel(); @@ -171,25 +163,6 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { } return t; } - - @SuppressWarnings("ConstantConditions") - private String resolveSemverVersion(ExecutionContext ctx, String groupId, String artifactId, @Nullable String currentVersion) throws MavenDownloadingException { - if (versionComparator == null) { - return newVersion; - } - String finalCurrentVersion = currentVersion != null ? currentVersion : newVersion; - if (availableVersions == null) { - availableVersions = new ArrayList<>(); - MavenMetadata mavenMetadata = metadataFailures.insertRows(ctx, () -> downloadMetadata(groupId, artifactId, ctx)); - for (String v : mavenMetadata.getVersioning().getVersions()) { - if (versionComparator.isValid(finalCurrentVersion, v)) { - availableVersions.add(v); - } - } - - } - return availableVersions.isEmpty() ? newVersion : Collections.max(availableVersions, versionComparator); - } }; } } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactIdTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactIdTest.java index c161d490a51..6cf15b5a4ab 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactIdTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactIdTest.java @@ -1194,6 +1194,73 @@ void changeGroupIdOnWildcardArtifacts() { ); } + @Test + void removeUnusedDependencyInManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + javax.activation + javax.activation-api + 1.2.0 + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + + javax.activation + javax.activation-api + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + + jakarta.activation + jakarta.activation-api + + + + """ + ) + ); + } + @Test void changeProfileDependencyGroupIdAndArtifactId() { rewriteRun( @@ -1247,4 +1314,275 @@ void changeProfileDependencyGroupIdAndArtifactId() { ) ); } + + @Test + void changePropertyVersionProfileManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + test + + + javax.activation + javax.activation-api + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + test + + + jakarta.activation + jakarta.activation-api + + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionProfileDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionProfileDependencyWithChangePropertyNameTrue() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + false, + true, + true + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + """ + ) + ); + } } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyVersionValueTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyVersionValueTest.java new file mode 100644 index 00000000000..080261b8f55 --- /dev/null +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyVersionValueTest.java @@ -0,0 +1,936 @@ +/* + * 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.assertj.core.api.Assertions.assertThat; +import static org.openrewrite.maven.Assertions.pomXml; + +class ChangeDependencyVersionValueTest implements RewriteTest { + + @DocumentExample + @Test + void changeVersionValue() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + """ + ) + ); + } + + @Test + void changeVersionValueWithDynamicVersion() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.x", + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + """, + spec -> spec.after(pom -> { + assertThat(pom).containsPattern("2.1.(\\d+)"); + return pom; + }) + ) + ); + } + + @Test + void latestPatchVersionValue() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "latest.patch", + null, + false, + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + jakarta.activation + jakarta.activation-api + 1.2.2 + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionValue() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + """ + ) + ); + } + + @Test + void changeProfileManagedDependencyVersionValue() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionProfileManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + ChangeDependencyVersionValue.VersionLocation.MANAGED_DEPENDENCY.name() + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + """ + ) + ); + } + + @Test + void changeEveryVersionOfEveryDependencyWithChangePropertyVersionName() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true, + null, + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + + + + jakarta.activation + jakarta.activation-api + 2.1.0 + + + + + + + + + """ + ) + ); + } + + @Test + void changeOnlyTheVersionOfProfileManagedDependencyWithChangePropertyVersionName() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true, + null, + "MANAGED_DEPENDENCY" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """ + ) + ); + } + + @Test + void changeOnlyTheVersionOfDependencyWithChangePropertyVersionName() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true, + null, + "DEPENDENCY" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """ + ) + ); + } + + @Test + void changeOnlyTheVersionOfPluginDependencyWithChangePropertyVersionName() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true, + null, + "PLUGIN_DEPENDENCY" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + + + + """ + ) + ); + } + + @Test + void changeOnlyTheVersionOfProfileManagedDependencyWithNewPropertyVersionName() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + false, + "test", + "MANAGED_DEPENDENCY" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + jakarta.activation + jakarta.activation-api + ${test} + + + + + + + + + jakarta.activation + jakarta.activation-api + 1.2.0 + + + + + + + + + """ + ) + ); + } + + @Test + void alreadyLatestVersionButWithPropertyChange() { + rewriteRun( + spec -> spec.recipe(new ChangeDependencyVersionValue( + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true, + "test", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${test} + + + + + + + """ + ) + ); + } +} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactIdTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactIdTest.java index b1458dda26d..e799e6544c4 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactIdTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactIdTest.java @@ -177,6 +177,61 @@ void latestPatchMangedDependency() { ); } + @Test + void changePropertyVersionManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeManagedDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + """ + ) + ); + } + @Test void changeProfileManagedDependencyGroupIdAndArtifactId() { rewriteRun( @@ -233,4 +288,136 @@ void changeProfileManagedDependencyGroupIdAndArtifactId() { ) ); } + + @Test + void changePropertyVersionProfileManagedDependency() { + rewriteRun( + spec -> spec.recipe(new ChangeManagedDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0" + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${javax.activation.version} + + + + + + + """ + ) + ); + } + + @Test + void changePropertyVersionProfileManagedDependencyWithChangePropertyVersionNameTrue() { + rewriteRun( + spec -> spec.recipe(new ChangeManagedDependencyGroupIdAndArtifactId( + "javax.activation", + "javax.activation-api", + "jakarta.activation", + "jakarta.activation-api", + "2.1.0", + null, + true + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 1.2.0 + + + + test + + + + javax.activation + javax.activation-api + ${javax.activation.version} + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + 2.1.0 + + + + test + + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation-api.version} + + + + + + + """ + ) + ); + } }