Skip to content

Commit be3e0ef

Browse files
committed
Add repository has dependency precondition for use limiting recipes to applying only to repositories that have a particular dependency.
1 parent 4665aa4 commit be3e0ef

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.dependencies.search;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.Value;
20+
import org.jspecify.annotations.Nullable;
21+
import org.openrewrite.*;
22+
import org.openrewrite.java.dependencies.DependencyInsight;
23+
import org.openrewrite.java.marker.JavaProject;
24+
import org.openrewrite.marker.SearchResult;
25+
26+
import java.util.concurrent.atomic.AtomicBoolean;
27+
28+
@Value
29+
@EqualsAndHashCode(callSuper = false)
30+
public class RepositoryHasDependency extends ScanningRecipe<AtomicBoolean> {
31+
32+
@Override
33+
public String getDisplayName() {
34+
return "Repository has dependency";
35+
}
36+
37+
@Override
38+
public String getDescription() {
39+
return "Searches for both Gradle and Maven modules that have a dependency matching the specified groupId and artifactId. " +
40+
"Places a `SearchResult` marker on all sources within a repository with a matching dependency. " +
41+
"This recipe is intended to be used as a precondition for other recipes. " +
42+
"For example this could be used to limit the application of a spring boot migration to only projects " +
43+
"that use a springframework dependency, limiting unnecessary upgrading. " +
44+
"If the search result you want is instead just the build.gradle(.kts) or pom.xml file applying the plugin, use the `FindDependency` recipe instead.";
45+
}
46+
47+
@Option(displayName = "Group pattern",
48+
description = "Group glob pattern used to match dependencies.",
49+
example = "com.fasterxml.jackson.module")
50+
String groupIdPattern;
51+
52+
@Option(displayName = "Artifact pattern",
53+
description = "Artifact glob pattern used to match dependencies.",
54+
example = "jackson-module-*")
55+
String artifactIdPattern;
56+
57+
@Option(displayName = "Scope",
58+
description = "Match dependencies with the specified scope. All scopes are searched by default.",
59+
valid = {"compile", "test", "runtime", "provided", "system"},
60+
example = "compile",
61+
required = false)
62+
@Nullable
63+
String scope;
64+
65+
@Option(displayName = "Version",
66+
description = "Match only dependencies with the specified version. " +
67+
"Node-style [version selectors](https://docs.openrewrite.org/reference/dependency-version-selectors) may be used." +
68+
"All versions are searched by default.",
69+
example = "1.x",
70+
required = false)
71+
@Nullable
72+
String version;
73+
74+
@Override
75+
public AtomicBoolean getInitialValue(ExecutionContext ctx) {
76+
return new AtomicBoolean();
77+
}
78+
79+
@Override
80+
public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean acc) {
81+
return new TreeVisitor<Tree, ExecutionContext>() {
82+
@Override
83+
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
84+
if(acc.get()) {
85+
assert tree != null;
86+
return tree;
87+
}
88+
assert tree != null;
89+
tree.getMarkers()
90+
.findFirst(JavaProject.class)
91+
.ifPresent(jp -> {
92+
Tree t = new DependencyInsight(groupIdPattern, artifactIdPattern, scope, version)
93+
.getVisitor()
94+
.visit(tree, ctx);
95+
if (t != tree) {
96+
acc.set(true);
97+
}
98+
});
99+
return tree;
100+
}
101+
};
102+
}
103+
104+
@Override
105+
public TreeVisitor<?, ExecutionContext> getVisitor(AtomicBoolean acc) {
106+
if (acc.get()) {
107+
return new TreeVisitor<Tree, ExecutionContext>() {
108+
@Override
109+
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
110+
assert tree != null;
111+
return SearchResult.found(tree, "Repository has dependency: " + groupIdPattern + ":" + artifactIdPattern + (version == null ? "" : ":" + version));
112+
}
113+
};
114+
} else {
115+
return TreeVisitor.noop();
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)