Skip to content

Add AddPlatformDependency recipe. #5371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
40f9c40
Add AddPlatformDependency recipe.
BrendanHart May 3, 2025
e43ac94
Apply suggestions from code review
BrendanHart May 3, 2025
672f9c0
Refactor common logic from AddDependency and AddPlatformDependency.
BrendanHart May 5, 2025
15b06e3
Rename class and add header.
BrendanHart May 5, 2025
c912310
Add header.
BrendanHart May 5, 2025
0366e13
Update rewrite-gradle/src/main/java/org/openrewrite/gradle/GradleConf…
BrendanHart May 5, 2025
07dd92c
Make util classes package private. Add test cases.
BrendanHart May 11, 2025
a803c8d
Merge branch 'main' into add-platform-dependency-recipe
BrendanHart May 11, 2025
dfd3969
Correct test config.
BrendanHart May 12, 2025
fe679b8
Merge branch 'main' into add-platform-dependency-recipe
BrendanHart May 12, 2025
1c035f3
Merge branch 'main' into add-platform-dependency-recipe
timtebeek May 19, 2025
5701d19
Cleanup
jevanlingen May 27, 2025
ad8940c
Merge remote-tracking branch 'origin/main' into add-platform-dependen…
shanman190 Jun 4, 2025
d107979
Introduce JvmTestSuite trait
shanman190 Jun 5, 2025
d4e655c
Merge branch 'add-platform-dependency-recipe' of github.com:BrendanHa…
shanman190 Jun 5, 2025
7fa7730
Add missing license header
shanman190 Jun 5, 2025
eea2f46
Update rewrite-gradle/src/test/java/org/openrewrite/gradle/trait/JvmT…
shanman190 Jun 5, 2025
ce270c1
Remove some now obsolete code
shanman190 Jun 5, 2025
b7584a2
Fix broken tests
shanman190 Jun 5, 2025
96ca571
Add error to first element being visited
shanman190 Jun 6, 2025
d01c721
Remove unused method
shanman190 Jun 6, 2025
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
113 changes: 23 additions & 90 deletions rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.gradle.marker.GradleDependencyConfiguration;
import org.openrewrite.gradle.marker.GradleProject;
import org.openrewrite.gradle.search.FindJVMTestSuites;
import org.openrewrite.gradle.trait.JvmTestSuite;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.marker.JavaProject;
Expand All @@ -30,13 +30,12 @@
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaSourceFile;
import org.openrewrite.maven.table.MavenMetadataFailures;
import org.openrewrite.maven.tree.GroupArtifact;
import org.openrewrite.semver.Semver;

import java.util.*;
import java.util.function.Predicate;

import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;

@Value
@EqualsAndHashCode(callSuper = false)
Expand Down Expand Up @@ -144,7 +143,6 @@ public Validated<Object> validate() {
public static class Scanned {
Map<JavaProject, Boolean> usingType = new HashMap<>();
Map<JavaProject, Set<String>> configurationsByProject = new HashMap<>();
Map<JavaProject, Set<String>> customJvmTestSuitesWithDependencies = new HashMap<>();
}

@Override
Expand Down Expand Up @@ -177,9 +175,6 @@ private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) {
SourceFile sourceFile = (SourceFile) tree;
sourceFile.getMarkers().findFirst(JavaProject.class).ifPresent(javaProject -> {
acc.usingType.compute(javaProject, (jp, usingType) -> Boolean.TRUE.equals(usingType) || usesType(sourceFile, ctx));
acc.customJvmTestSuitesWithDependencies
.computeIfAbsent(javaProject, ignored -> new HashSet<>())
.addAll(FindJVMTestSuites.jvmTestSuiteNames(tree, true));

Set<String> configurations = acc.configurationsByProject.computeIfAbsent(javaProject, ignored -> new HashSet<>());
sourceFile.getMarkers().findFirst(JavaSourceSet.class).ifPresent(sourceSet ->
Expand All @@ -202,20 +197,14 @@ public TreeVisitor<?, ExecutionContext> getVisitor(Scanned acc) {
}
JavaSourceFile s = (JavaSourceFile) tree;
Optional<JavaProject> maybeJp = s.getMarkers().findFirst(JavaProject.class);
if (!maybeJp.isPresent()) {
return s;
}

JavaProject jp = maybeJp.get();
if ((onlyIfUsing != null && !acc.usingType.getOrDefault(jp, false)) || !acc.configurationsByProject.containsKey(jp)) {
return s;
}

Optional<GradleProject> maybeGp = s.getMarkers().findFirst(GradleProject.class);
if (!maybeGp.isPresent()) {
if (!maybeJp.isPresent() ||
(onlyIfUsing != null && !acc.usingType.getOrDefault(maybeJp.get(), false)) || !acc.configurationsByProject.containsKey(maybeJp.get()) ||
!maybeGp.isPresent()) {
return s;
}

JavaProject jp = maybeJp.get();
GradleProject gp = maybeGp.get();

Set<String> resolvedConfigurations = StringUtils.isBlank(configuration) ?
Expand All @@ -224,36 +213,26 @@ public TreeVisitor<?, ExecutionContext> getVisitor(Scanned acc) {
if (resolvedConfigurations.isEmpty()) {
resolvedConfigurations.add("implementation");
}
Set<String> tmpConfigurations = new HashSet<>(resolvedConfigurations);
for (String tmpConfiguration : tmpConfigurations) {
GradleDependencyConfiguration gdc = gp.getConfiguration(tmpConfiguration);
if (gdc == null || gdc.findRequestedDependency(groupId, artifactId) != null) {
resolvedConfigurations.remove(tmpConfiguration);
}
}

tmpConfigurations = new HashSet<>(resolvedConfigurations);
for (String tmpConfiguration : tmpConfigurations) {
GradleDependencyConfiguration gdc = requireNonNull((gp.getConfiguration(tmpConfiguration)));
for (GradleDependencyConfiguration transitive : gp.configurationsExtendingFrom(gdc, true)) {
if (resolvedConfigurations.contains(transitive.getName()) ||
(Boolean.TRUE.equals(acceptTransitive) && transitive.findResolvedDependency(groupId, artifactId) != null)) {
resolvedConfigurations.remove(transitive.getName());
}
}
}
GradleConfigurationFilter gradleConfigurationFilter = new GradleConfigurationFilter(gp, resolvedConfigurations);
gradleConfigurationFilter.removeTransitiveConfigurations();
gradleConfigurationFilter.removeConfigurationsContainingDependency(new GroupArtifact(groupId, artifactId));
gradleConfigurationFilter.removeConfigurationsContainingTransitiveDependency(new GroupArtifact(groupId, artifactId));
resolvedConfigurations = gradleConfigurationFilter.getFilteredConfigurations();

if (resolvedConfigurations.isEmpty()) {
return s;
}

Set<JvmTestSuite> jvmTestSuites = FindJVMTestSuites.jvmTestSuites(s);
for (String resolvedConfiguration : resolvedConfigurations) {
if (targetsCustomJVMTestSuite(resolvedConfiguration, acc.customJvmTestSuitesWithDependencies.get(jp))) {
s = (JavaSourceFile) new AddDependencyVisitor(groupId, artifactId, version, versionPattern, purgeSourceSet(configuration),
classifier, extension, metadataFailures, isMatchingJVMTestSuite(resolvedConfiguration)).visitNonNull(s, ctx);
JvmTestSuite jvmTestSuite = maybeJvmTestSuite(resolvedConfiguration, jvmTestSuites);
if (jvmTestSuite != null) {
s = (JavaSourceFile) jvmTestSuite.addDependency(resolvedConfiguration, groupId, artifactId, version, versionPattern, classifier, extension, metadataFailures, null, ctx)
.visitNonNull(s, ctx);
} else {
s = (JavaSourceFile) new AddDependencyVisitor(groupId, artifactId, version, versionPattern, resolvedConfiguration,
classifier, extension, metadataFailures, this::isTopLevel).visitNonNull(s, ctx);
classifier, extension, metadataFailures, this::isTopLevel, null).visitNonNull(s, ctx);
}
}

Expand All @@ -264,59 +243,13 @@ private boolean isTopLevel(Cursor cursor) {
return cursor.getParentOrThrow().firstEnclosing(J.MethodInvocation.class) == null;
}

private Predicate<Cursor> isMatchingJVMTestSuite(String resolvedConfiguration) {
return cursor -> {
String sourceSet = purgeConfigurationSuffix(resolvedConfiguration);
J.MethodInvocation methodInvocation = cursor.getParentOrThrow().firstEnclosing(J.MethodInvocation.class);
return methodInvocation != null && sourceSet.equals(methodInvocation.getSimpleName());
};
}

private final Set<String> gradleStandardConfigurations = new HashSet<>(Arrays.asList(
"api",
"implementation",
"compileOnly",
"compileOnlyApi",
"runtimeOnly",
"testImplementation",
"testCompileOnly",
"testRuntimeOnly"));

boolean targetsCustomJVMTestSuite(String configuration, Set<String> customJvmTestSuites) {
if (gradleStandardConfigurations.contains(configuration) || "default".equals(configuration)) {
return false;
}

String sourceSet = purgeConfigurationSuffix(configuration);
return customJvmTestSuites.contains(sourceSet);
}

private String purgeConfigurationSuffix(String configuration) {
if (configuration.endsWith("Implementation")) {
return configuration.substring(0, configuration.length() - 14);
} else if (configuration.endsWith("CompileOnly")) {
return configuration.substring(0, configuration.length() - 11);
} else if (configuration.endsWith("RuntimeOnly")) {
return configuration.substring(0, configuration.length() - 11);
} else if (configuration.endsWith("AnnotationProcessor")) {
return configuration.substring(0, configuration.length() - 19);
} else {
return configuration;
}
}

private String purgeSourceSet(@Nullable String configuration) {
if (StringUtils.isBlank(configuration) || configuration.endsWith("Implementation")) {
return "implementation";
} else if (configuration.endsWith("CompileOnly")) {
return "compileOnly";
} else if (configuration.endsWith("RuntimeOnly")) {
return "runtimeOnly";
} else if (configuration.endsWith("AnnotationProcessor")) {
return "annotationProcessor";
} else {
return configuration;
private @Nullable JvmTestSuite maybeJvmTestSuite(String configuration, Set<JvmTestSuite> jvmTestSuites) {
for (JvmTestSuite jvmTestSuite : jvmTestSuites) {
if (jvmTestSuite.isAcceptable(configuration)) {
return jvmTestSuite;
}
}
return null;
}
})
);
Expand Down
Loading
Loading