Skip to content

Commit d890c71

Browse files
Fixed situation where a changing a managed dependency that does not have an explicit version tag would fail to add a version tag when providing the newVersion option. (#6105)
* Fixed situation where a changing a managed dependency that does not have an explicit `version` tag would fail to add a `version` tag when providing the `newVersion` option. * WiP - refining prevention of version tag creation on direct dependency. Delegating `maybeUpdateModel()` call to implied `ChangeManagedDependencyGroupIdAndArtifactId` in applicable cases to avoid interim dependency resolution failure. * Slight cleanup. One test still failing. Need to revisit validity of change proposed in the test itself. * Adjusted check for managed dependency to be able to traverse through local parent POMs and only consider those managed dependencies that are actually defined in the requested set of managed dependencies, rather than those that get resolved via an import managed dependency. Tidied up some method names and renamed a test to better represent what it's actually doing. * Corrected `<type>bom</type>` to `<type>pom</type>` in tests, and added a more complicated example for `ChangeDependencyGroupIdAndArtifactId`
1 parent 1c2c355 commit d890c71

File tree

5 files changed

+545
-24
lines changed

5 files changed

+545
-24
lines changed

rewrite-maven/src/main/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactId.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
147147

148148
@Override
149149
public Xml visitDocument(Xml.Document document, ExecutionContext ctx) {
150-
isNewDependencyPresent = checkIfNewDependencyPresents(newGroupId, newArtifactId, newVersion);
150+
isNewDependencyPresent = checkIfNewDependencyPresent(newGroupId, newArtifactId, newVersion);
151151
if (!oldGroupId.contains("*") && !oldArtifactId.contains("*") &&
152152
(changeManagedDependency == null || changeManagedDependency)) {
153153
doAfterVisit(new ChangeManagedDependencyGroupIdAndArtifactId(
@@ -170,16 +170,26 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
170170
}
171171
boolean isPluginDependency = isPluginDependencyTag(oldGroupId, oldArtifactId);
172172
boolean isAnnotationProcessorPath = isAnnotationProcessorPathTag(oldGroupId, oldArtifactId);
173+
boolean deferUpdate = false;
173174
if (isOldDependencyTag || isPluginDependency || isAnnotationProcessorPath) {
175+
ResolvedPom rp = getResolutionResult().getPom();
174176
String groupId = newGroupId;
175177
if (groupId != null) {
176-
t = changeChildTagValue(t, "groupId", groupId, ctx);
178+
Optional<Xml.Tag> groupIdTag = t.getChild("groupId");
179+
Optional<String> groupIdValue = t.getChildValue("groupId");
180+
if (groupIdTag.isPresent() && !groupId.equals(rp.getValue(groupIdValue.orElse(null)))) {
181+
t = changeChildTagValue(t, "groupId", groupId, ctx);
182+
}
177183
} else {
178184
groupId = t.getChildValue("groupId").orElseThrow(NoSuchElementException::new);
179185
}
180186
String artifactId = newArtifactId;
181187
if (artifactId != null) {
182-
t = changeChildTagValue(t, "artifactId", artifactId, ctx);
188+
Optional<Xml.Tag> artifactIdTag = t.getChild("artifactId");
189+
Optional<String> artifactIdValue = t.getChildValue("artifactId");
190+
if (artifactIdTag.isPresent() && !artifactId.equals(rp.getValue(artifactIdValue.orElse(null)))) {
191+
t = changeChildTagValue(t, "artifactId", artifactId, ctx);
192+
}
183193
} else {
184194
artifactId = t.getChildValue("artifactId").orElseThrow(NoSuchElementException::new);
185195
}
@@ -192,33 +202,37 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
192202
Scope scope = scopeTag.map(xml -> Scope.fromName(xml.getValue().orElse("compile"))).orElse(Scope.Compile);
193203
Optional<Xml.Tag> versionTag = t.getChild("version");
194204

195-
boolean configuredToOverrideManageVersion = overrideManagedVersion != null && overrideManagedVersion; // False by default
205+
boolean configuredToOverrideManagedVersion = overrideManagedVersion != null && overrideManagedVersion; // False by default
196206
boolean configuredToChangeManagedDependency = changeManagedDependency == null || changeManagedDependency; // True by default
197207

198208
boolean versionTagPresent = versionTag.isPresent();
199209
// dependencyManagement does not apply to plugin dependencies or annotation processor paths
200-
boolean oldDependencyManaged = isOldDependencyTag && isDependencyManaged(scope, oldGroupId, oldArtifactId);
210+
boolean oldDependencyDefinedManaged = isOldDependencyTag && canAffectManagedDependency(getResolutionResult(), scope, oldGroupId, oldArtifactId);
201211
boolean newDependencyManaged = isOldDependencyTag && isDependencyManaged(scope, groupId, artifactId);
212+
202213
if (versionTagPresent) {
203214
// If the previous dependency had a version but the new artifact is managed, removed the version tag.
204-
if (!configuredToOverrideManageVersion && newDependencyManaged || (oldDependencyManaged && configuredToChangeManagedDependency)) {
215+
if (!configuredToOverrideManagedVersion && newDependencyManaged || (oldDependencyDefinedManaged && configuredToChangeManagedDependency)) {
205216
t = (Xml.Tag) new RemoveContentVisitor<>(versionTag.get(), false, true).visit(t, ctx);
206217
} else {
207218
// Otherwise, change the version to the new value.
208219
t = changeChildTagValue(t, "version", resolvedNewVersion, ctx);
209220
}
210-
} else if (configuredToOverrideManageVersion || !newDependencyManaged) {
211-
//If the version is not present, add the version if we are explicitly overriding a managed version or if no managed version exists.
221+
} else if (configuredToOverrideManagedVersion || (!newDependencyManaged && !(oldDependencyDefinedManaged && configuredToChangeManagedDependency))) {
222+
// If the version is not present, add the version if we are explicitly overriding a managed version or if no managed version exists.
212223
Xml.Tag newVersionTag = Xml.Tag.build("<version>" + resolvedNewVersion + "</version>");
213224
//noinspection ConstantConditions
214225
t = (Xml.Tag) new AddToTagVisitor<ExecutionContext>(t, newVersionTag, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParent());
226+
} else if (!newDependencyManaged) {
227+
// We leave it up to the managed dependency update to call `maybeUpdateModel()` instead to avoid interim dependency resolution failure
228+
deferUpdate = true;
215229
}
216230
} catch (MavenDownloadingException e) {
217231
return e.warn(tag);
218232
}
219233
}
220234

221-
if (t != tag) {
235+
if (t != tag && !deferUpdate) {
222236
maybeUpdateModel();
223237
}
224238
}
@@ -227,7 +241,7 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
227241
return t;
228242
}
229243

230-
private boolean checkIfNewDependencyPresents(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
244+
private boolean checkIfNewDependencyPresent(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
231245
if ((groupId == null) || (artifactId == null)) {
232246
return false;
233247
}
@@ -248,6 +262,23 @@ private boolean isDependencyManaged(Scope scope, String groupId, String artifact
248262
return false;
249263
}
250264

265+
private boolean canAffectManagedDependency(MavenResolutionResult result, Scope scope, String groupId, String artifactId) {
266+
// We're only going to be able to effect managed dependencies that are either direct or are brought in as direct via a local parent
267+
// `ChangeManagedDependencyGroupIdAndArtifactId` cannot manipulate BOM imported managed dependencies nor direct dependencies from remote parents
268+
Pom requestedPom = result.getPom().getRequested();
269+
for (ManagedDependency requestedManagedDependency : requestedPom.getDependencyManagement()) {
270+
if (groupId.equals(requestedManagedDependency.getGroupId()) && artifactId.equals(requestedManagedDependency.getArtifactId())) {
271+
if (requestedManagedDependency instanceof ManagedDependency.Defined) {
272+
return scope.isInClasspathOf(Scope.fromName(((ManagedDependency.Defined) requestedManagedDependency).getScope()));
273+
}
274+
}
275+
}
276+
if (result.parentPomIsProjectPom() && result.getParent() != null) {
277+
return canAffectManagedDependency(result.getParent(), scope, groupId, artifactId);
278+
}
279+
return false;
280+
}
281+
251282
@SuppressWarnings("ConstantConditions")
252283
private String resolveSemverVersion(ExecutionContext ctx, String groupId, String artifactId, @Nullable String currentVersion) throws MavenDownloadingException {
253284
if (versionComparator == null) {

rewrite-maven/src/main/java/org/openrewrite/maven/ChangeManagedDependencyGroupIdAndArtifactId.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.openrewrite.maven.tree.ResolvedPom;
2727
import org.openrewrite.semver.Semver;
2828
import org.openrewrite.semver.VersionComparator;
29+
import org.openrewrite.xml.AddToTagVisitor;
2930
import org.openrewrite.xml.RemoveContentVisitor;
3031
import org.openrewrite.xml.tree.Xml;
3132

@@ -128,7 +129,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
128129

129130
@Override
130131
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
131-
isNewDependencyPresent = checkIfNewDependencyPresents(newGroupId, newArtifactId, newVersion);
132+
isNewDependencyPresent = checkIfNewDependencyPresent(newGroupId, newArtifactId, newVersion);
132133
return super.visitDocument(document, ctx);
133134
}
134135

@@ -154,6 +155,9 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
154155
}
155156
String resolvedNewVersion = resolveSemverVersion(ctx, newGroupId, resolvedArtifactId, getResolutionResult().getPom().getValue(versionTag.get().getValue().orElse(null)));
156157
t = changeChildTagValue(t, "version", resolvedNewVersion, ctx);
158+
} else {
159+
Xml.Tag newChild = Xml.Tag.build("<version>" + newVersion + "</version>");
160+
t = (Xml.Tag) new AddToTagVisitor<ExecutionContext>(t, newChild, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParentOrThrow());
157161
}
158162
} catch (MavenDownloadingException e) {
159163
return e.warn(t);
@@ -171,7 +175,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
171175
return t;
172176
}
173177

174-
private boolean checkIfNewDependencyPresents(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
178+
private boolean checkIfNewDependencyPresent(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
175179
if ((groupId == null) || (artifactId == null)) {
176180
return false;
177181
}

0 commit comments

Comments
 (0)