Skip to content

Commit 11bdbd5

Browse files
committed
Merge Groovy/Kotlin visitors into single JavaIsoVisitor in UpdateJavaCompatibility
1 parent 9b49f1c commit 11bdbd5

1 file changed

Lines changed: 104 additions & 107 deletions

File tree

rewrite-gradle/src/main/java/org/openrewrite/gradle/UpdateJavaCompatibility.java

Lines changed: 104 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
import org.jspecify.annotations.Nullable;
2121
import org.openrewrite.*;
2222
import org.openrewrite.gradle.internal.ChangeStringLiteral;
23-
import org.openrewrite.groovy.GroovyIsoVisitor;
2423
import org.openrewrite.groovy.tree.G;
2524
import org.openrewrite.internal.ListUtils;
2625
import org.openrewrite.java.JavaIsoVisitor;
2726
import org.openrewrite.java.MethodMatcher;
2827
import org.openrewrite.java.tree.*;
29-
import org.openrewrite.kotlin.KotlinIsoVisitor;
3028
import org.openrewrite.kotlin.KotlinParser;
3129
import org.openrewrite.kotlin.tree.K;
3230
import org.openrewrite.marker.Markers;
@@ -44,6 +42,8 @@
4442
public class UpdateJavaCompatibility extends Recipe {
4543
private static final MethodMatcher SOURCE_COMPATIBILITY_DSL = new MethodMatcher("org.gradle.api.Project setSourceCompatibility(..)", true);
4644
private static final MethodMatcher TARGET_COMPATIBILITY_DSL = new MethodMatcher("org.gradle.api.Project setTargetCompatibility(..)", true);
45+
private static final MethodMatcher SOURCE_COMPATIBILITY_METHOD = new MethodMatcher("org.gradle.api.Project sourceCompatibility(..)", true);
46+
private static final MethodMatcher TARGET_COMPATIBILITY_METHOD = new MethodMatcher("org.gradle.api.Project targetCompatibility(..)", true);
4747

4848
@Option(displayName = "Java version",
4949
description = "The Java version to upgrade to.",
@@ -78,9 +78,6 @@ public class UpdateJavaCompatibility extends Recipe {
7878
@Nullable
7979
Boolean addIfMissing;
8080

81-
private static final String SOURCE_COMPATIBILITY_FOUND = "SOURCE_COMPATIBILITY_FOUND";
82-
private static final String TARGET_COMPATIBILITY_FOUND = "TARGET_COMPATIBILITY_FOUND";
83-
8481
String displayName = "Update Gradle project Java compatibility";
8582

8683
String description = "Find and updates the Java compatibility for the Gradle project.";
@@ -92,118 +89,124 @@ public Validated<Object> validate() {
9289

9390
@Override
9491
public TreeVisitor<?, ExecutionContext> getVisitor() {
95-
return Preconditions.check(new IsBuildGradle<>(), Preconditions.or(new GroovyScriptVisitor(), new KotlinScriptVisitor()));
96-
}
97-
98-
private class GroovyScriptVisitor extends GroovyIsoVisitor<ExecutionContext> {
99-
@Override
100-
public G.CompilationUnit visitCompilationUnit(G.CompilationUnit cu, ExecutionContext ctx) {
101-
G.CompilationUnit c = super.visitCompilationUnit(cu, ctx);
102-
if (getCursor().pollMessage(SOURCE_COMPATIBILITY_FOUND) == null) {
103-
c = addCompatibilityTypeToSourceFile(c, "source", ctx);
104-
}
105-
if (getCursor().pollMessage(TARGET_COMPATIBILITY_FOUND) == null) {
106-
c = addCompatibilityTypeToSourceFile(c, "target", ctx);
92+
return Preconditions.check(new IsBuildGradle<>(), new JavaIsoVisitor<ExecutionContext>() {
93+
boolean sourceCompatibilityFound;
94+
boolean targetCompatibilityFound;
95+
96+
@Override
97+
public @Nullable J visit(@Nullable Tree tree, ExecutionContext ctx) {
98+
if (!(tree instanceof SourceFile)) {
99+
return super.visit(tree, ctx);
100+
}
101+
sourceCompatibilityFound = false;
102+
targetCompatibilityFound = false;
103+
J visited = super.visit(tree, ctx);
104+
if (visited instanceof G.CompilationUnit) {
105+
G.CompilationUnit c = (G.CompilationUnit) visited;
106+
if (!sourceCompatibilityFound) {
107+
c = addGroovyCompatibilityType(c, "source", ctx);
108+
}
109+
if (!targetCompatibilityFound) {
110+
c = addGroovyCompatibilityType(c, "target", ctx);
111+
}
112+
return c;
113+
} else if (visited instanceof K.CompilationUnit) {
114+
K.CompilationUnit c = (K.CompilationUnit) visited;
115+
if (!sourceCompatibilityFound) {
116+
c = addKotlinCompatibilityType(c, "source", ctx);
117+
}
118+
if (!targetCompatibilityFound) {
119+
c = addKotlinCompatibilityType(c, "target", ctx);
120+
}
121+
return c;
122+
}
123+
return visited;
107124
}
108-
return c;
109-
}
110-
111-
@Override
112-
public J.Assignment visitAssignment(J.Assignment assignment, ExecutionContext ctx) {
113-
return handleAssignment(super.visitAssignment(assignment, ctx), getCursor(), G.CompilationUnit.class);
114-
}
115125

116-
@Override
117-
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
118-
return handleMethodInvocation(super.visitMethodInvocation(method, ctx), getCursor(), G.CompilationUnit.class);
119-
}
126+
@Override
127+
public J.Assignment visitAssignment(J.Assignment assignment, ExecutionContext ctx) {
128+
J.Assignment a = super.visitAssignment(assignment, ctx);
129+
if (a.getVariable() instanceof J.Identifier) {
130+
J.Identifier variable = (J.Identifier) a.getVariable();
131+
if ("sourceCompatibility".equals(variable.getSimpleName())) {
132+
sourceCompatibilityFound = true;
133+
}
134+
if ("targetCompatibility".equals(variable.getSimpleName())) {
135+
targetCompatibilityFound = true;
136+
}
137+
}
138+
return handleAssignment(a);
139+
}
120140

121-
private G.CompilationUnit addCompatibilityTypeToSourceFile(G.CompilationUnit c, String targetCompatibilityType, ExecutionContext ctx) {
122-
if ((compatibilityType == null || targetCompatibilityType.equals(compatibilityType.toString())) && TRUE.equals(addIfMissing)) {
123-
G.CompilationUnit sourceFile = (G.CompilationUnit) GradleParser.builder().build()
124-
.parse(ctx, "\n" + targetCompatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(declarationStyle))
125-
.findFirst()
126-
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
127-
c = c.withStatements(ListUtils.concatAll(c.getStatements(), sourceFile.getStatements()));
141+
@Override
142+
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
143+
J.MethodInvocation m = super.visitMethodInvocation(method, ctx);
144+
if (SOURCE_COMPATIBILITY_METHOD.matches(m) || SOURCE_COMPATIBILITY_DSL.matches(m)) {
145+
sourceCompatibilityFound = true;
146+
}
147+
if (TARGET_COMPATIBILITY_METHOD.matches(m) || TARGET_COMPATIBILITY_DSL.matches(m)) {
148+
targetCompatibilityFound = true;
149+
}
150+
return handleMethodInvocation(m);
128151
}
129-
return c;
130-
}
152+
});
131153
}
132154

133-
private class KotlinScriptVisitor extends KotlinIsoVisitor<ExecutionContext> {
134-
@Override
135-
public K.CompilationUnit visitCompilationUnit(K.CompilationUnit cu, ExecutionContext ctx) {
136-
K.CompilationUnit c = super.visitCompilationUnit(cu, ctx);
137-
if (getCursor().pollMessage(SOURCE_COMPATIBILITY_FOUND) == null) {
138-
c = addCompatibilityTypeToSourceFile(c, "source", ctx);
139-
}
140-
if (getCursor().pollMessage(TARGET_COMPATIBILITY_FOUND) == null) {
141-
c = addCompatibilityTypeToSourceFile(c, "target", ctx);
142-
}
143-
return super.visitCompilationUnit(c, ctx);
155+
private G.CompilationUnit addGroovyCompatibilityType(G.CompilationUnit c, String targetCompatibilityType, ExecutionContext ctx) {
156+
if ((compatibilityType == null || targetCompatibilityType.equals(compatibilityType.toString())) && TRUE.equals(addIfMissing)) {
157+
G.CompilationUnit sourceFile = (G.CompilationUnit) GradleParser.builder().build()
158+
.parse(ctx, "\n" + targetCompatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(declarationStyle))
159+
.findFirst()
160+
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
161+
c = c.withStatements(ListUtils.concatAll(c.getStatements(), sourceFile.getStatements()));
144162
}
163+
return c;
164+
}
145165

146-
@Override
147-
public J.Assignment visitAssignment(J.Assignment assignment, ExecutionContext ctx) {
148-
return handleAssignment(super.visitAssignment(assignment, ctx), getCursor(), K.CompilationUnit.class);
149-
}
166+
private K.CompilationUnit addKotlinCompatibilityType(K.CompilationUnit c, String targetCompatibilityType, ExecutionContext ctx) {
167+
if ((compatibilityType == null || targetCompatibilityType.equals(compatibilityType.toString())) && TRUE.equals(addIfMissing)) {
168+
J withExistingJavaMethod = maybeAddToExistingJavaMethod(c, targetCompatibilityType, ctx);
169+
if (withExistingJavaMethod != c) {
170+
return (K.CompilationUnit) withExistingJavaMethod;
171+
}
150172

151-
@Override
152-
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
153-
return handleMethodInvocation(super.visitMethodInvocation(method, ctx), getCursor(), K.CompilationUnit.class);
173+
K.CompilationUnit sourceFile = (K.CompilationUnit) KotlinParser.builder()
174+
.isKotlinScript(true)
175+
.build().parse(ctx, "\n\njava {\n " + targetCompatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(DeclarationStyle.Enum) + "\n}")
176+
.findFirst()
177+
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
178+
c = c.withStatements(ListUtils.concatAll(c.getStatements(), sourceFile.getStatements()));
154179
}
180+
return c;
181+
}
155182

156-
private K.CompilationUnit addCompatibilityTypeToSourceFile(K.CompilationUnit c, String targetCompatibilityType, ExecutionContext ctx) {
157-
if ((compatibilityType == null || targetCompatibilityType.equals(compatibilityType.toString())) && TRUE.equals(addIfMissing)) {
158-
J withExistingJavaMethod = maybeAddToExistingJavaMethod(c, targetCompatibilityType, ctx);
159-
if (withExistingJavaMethod != c) {
160-
return (K.CompilationUnit) withExistingJavaMethod;
183+
private J maybeAddToExistingJavaMethod(K.CompilationUnit c, String compatibilityType, ExecutionContext ctx) {
184+
return new JavaIsoVisitor<ExecutionContext>() {
185+
@Override
186+
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
187+
if ("java".equals(method.getSimpleName())) {
188+
return new JavaIsoVisitor<ExecutionContext>() {
189+
@Override
190+
public J.Lambda visitLambda(J.Lambda lambda, ExecutionContext ctx) {
191+
J.Block body = (J.Block) lambda.getBody();
192+
List<Statement> statements = body.getStatements();
193+
K.CompilationUnit sourceFile = (K.CompilationUnit) KotlinParser.builder()
194+
.isKotlinScript(true)
195+
.build().parse(ctx, "\n " + compatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(DeclarationStyle.Enum))
196+
.findFirst()
197+
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
198+
return lambda.withBody(body.withStatements(ListUtils.concatAll(statements, sourceFile.getStatements())));
199+
}
200+
}.visitMethodInvocation(method, ctx);
161201
}
162-
163-
K.CompilationUnit sourceFile = (K.CompilationUnit) KotlinParser.builder()
164-
.isKotlinScript(true)
165-
.build().parse(ctx, "\n\njava {\n " + targetCompatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(DeclarationStyle.Enum) + "\n}")
166-
.findFirst()
167-
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
168-
c = c.withStatements(ListUtils.concatAll(c.getStatements(), sourceFile.getStatements()));
202+
return super.visitMethodInvocation(method, ctx);
169203
}
170-
return c;
171-
}
172-
173-
private J maybeAddToExistingJavaMethod(K.CompilationUnit c, String compatibilityType, ExecutionContext ctx) {
174-
return new JavaIsoVisitor<ExecutionContext>() {
175-
@Override
176-
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
177-
if ("java".equals(method.getSimpleName())) {
178-
return new JavaIsoVisitor<ExecutionContext>() {
179-
@Override
180-
public J.Lambda visitLambda(J.Lambda lambda, ExecutionContext ctx) {
181-
J.Block body = (J.Block) lambda.getBody();
182-
List<Statement> statements = body.getStatements();
183-
K.CompilationUnit sourceFile = (K.CompilationUnit) KotlinParser.builder()
184-
.isKotlinScript(true)
185-
.build().parse(ctx, "\n " + compatibilityType + "Compatibility = " + styleMissingCompatibilityVersion(DeclarationStyle.Enum))
186-
.findFirst()
187-
.orElseThrow(() -> new IllegalStateException("Unable to parse compatibility type as a Gradle file"));
188-
return lambda.withBody(body.withStatements(ListUtils.concatAll(statements, sourceFile.getStatements())));
189-
}
190-
}.visitMethodInvocation(method, ctx);
191-
}
192-
return super.visitMethodInvocation(method, ctx);
193-
}
194-
}.visitNonNull(c, ctx);
195-
}
204+
}.visitNonNull(c, ctx);
196205
}
197206

198-
public J.Assignment handleAssignment(J.Assignment a, Cursor c, Class<?> enclosing) {
207+
private J.Assignment handleAssignment(J.Assignment a) {
199208
if (a.getVariable() instanceof J.Identifier) {
200209
J.Identifier variable = (J.Identifier) a.getVariable();
201-
if ("sourceCompatibility".equals(variable.getSimpleName())) {
202-
c.putMessageOnFirstEnclosing(enclosing, SOURCE_COMPATIBILITY_FOUND, true);
203-
}
204-
if ("targetCompatibility".equals(variable.getSimpleName())) {
205-
c.putMessageOnFirstEnclosing(enclosing, TARGET_COMPATIBILITY_FOUND, true);
206-
}
207210

208211
if (compatibilityType == null) {
209212
if (!("sourceCompatibility".equals(variable.getSimpleName()) || "targetCompatibility".equals(variable.getSimpleName()))) {
@@ -246,13 +249,7 @@ private boolean shouldUpdateStyle(@Nullable DeclarationStyle currentStyle) {
246249
return declarationStyle != null && declarationStyle != currentStyle;
247250
}
248251

249-
public J.MethodInvocation handleMethodInvocation(J.MethodInvocation m, Cursor c, Class<?> enclosing) {
250-
if ("sourceCompatibility".equals(m.getSimpleName())) {
251-
c.putMessageOnFirstEnclosing(enclosing, SOURCE_COMPATIBILITY_FOUND, true);
252-
}
253-
if ("targetCompatibility".equals(m.getSimpleName())) {
254-
c.putMessageOnFirstEnclosing(enclosing, TARGET_COMPATIBILITY_FOUND, true);
255-
}
252+
private J.MethodInvocation handleMethodInvocation(J.MethodInvocation m) {
256253
if ("jvmToolchain".equals(m.getSimpleName()) || isMethodInvocation(m, "JavaLanguageVersion", "of")) {
257254
List<Expression> args = m.getArguments();
258255

0 commit comments

Comments
 (0)