From 023925812991c6cf1b8e69fb2ae0bfb774f27f04 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Wed, 22 Apr 2026 14:55:59 -0400 Subject: [PATCH] Avoid triggering full transitive resolution from GradleDependencyConfiguration.findResolvedDependency findResolvedDependency iterates direct dependencies of the configuration looking for a match. It was calling getDirectResolved(), which triggers a full transitive download if the configuration has been marked for re-resolution (e.g. after AddDependency / UpgradeDependencyVersion / ChangeDependency mutations). Switch to getDirectResolvedShallow(), which resolves only the direct dependencies and defers the transitive closure until a caller actually walks it. The method is called from ChangeDependency, RemoveRedundantDependencyVersions, RemoveRedundantSecurityResolutionRules, GradleConfigurationFilter, and several downstream recipe repositories. In a migration recipe chain that rewrites many dependencies per build.gradle, each call was paying the full transitive-resolution cost. Updates one test (GradleProjectTest#changeConstraint) that searched for a transitive dependency via findResolvedDependency; it now iterates getResolved() directly, since the method is now scoped to direct dependencies of the configuration. --- .../gradle/marker/GradleDependencyConfiguration.java | 7 ++++++- .../openrewrite/gradle/marker/GradleProjectTest.java | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/marker/GradleDependencyConfiguration.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/marker/GradleDependencyConfiguration.java index b944ebbc832..8e045820275 100644 --- a/rewrite-gradle/src/main/java/org/openrewrite/gradle/marker/GradleDependencyConfiguration.java +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/marker/GradleDependencyConfiguration.java @@ -439,8 +439,13 @@ public List allExtendsFrom() { return null; } + /** + * Find a direct dependency of this configuration matching the given coordinates. This does not walk into the + * transitive closure of each direct dependency; use {@link #getResolved()} and iterate there if you need to + * match a transitive. Uses {@link #getDirectResolvedShallow()} so it does not trigger a full transitive download. + */ public @Nullable ResolvedDependency findResolvedDependency(@Nullable String groupId, String artifactId) { - for (ResolvedDependency d : getDirectResolved()) { + for (ResolvedDependency d : getDirectResolvedShallow()) { ResolvedDependency dependency = d.findDependency(groupId == null ? "" : groupId, artifactId); if (dependency != null) { return dependency; diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/marker/GradleProjectTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/marker/GradleProjectTest.java index 6f51f624b7a..d87842b667f 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/marker/GradleProjectTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/marker/GradleProjectTest.java @@ -554,10 +554,16 @@ void changeConstraint() { .extracting(GradleDependencyConstraint::getRequiredVersion) .isEqualTo("2.19.2"); - // Verify the runtimeClasspath has the updated resolved version + // Verify the runtimeClasspath has the updated resolved version. jackson-databind is a transitive + // of rewrite-core, so search the flat resolved list rather than findResolvedDependency (which is + // direct-only). GradleDependencyConfiguration runtimeClasspath = updated.getConfiguration("runtimeClasspath"); assertThat(runtimeClasspath).isNotNull(); - ResolvedDependency resolvedJackson = runtimeClasspath.findResolvedDependency("com.fasterxml.jackson.core", "jackson-databind"); + ResolvedDependency resolvedJackson = runtimeClasspath.getResolved().stream() + .filter(d -> "com.fasterxml.jackson.core".equals(d.getGroupId()) && + "jackson-databind".equals(d.getArtifactId())) + .findFirst() + .orElse(null); assertThat(resolvedJackson).isNotNull() .extracting(ResolvedDependency::getVersion) .as("jackson-databind should be resolved to the constrained version")