Skip to content

Commit d2a67c2

Browse files
committed
Gradle: rename mainClassName to mainClass in application block
The `mainClassName` property on the application extension was deprecated in Gradle 6.4 and removed in Gradle 9.0. Add a recipe that renames it inside the `application { ... }` block (Groovy and Kotlin DSL) and wire it into `MigrateToGradle9`.
1 parent c4774bb commit d2a67c2

3 files changed

Lines changed: 217 additions & 1 deletion

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2026 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.gradle.gradle9;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.Value;
20+
import org.openrewrite.ExecutionContext;
21+
import org.openrewrite.Preconditions;
22+
import org.openrewrite.Recipe;
23+
import org.openrewrite.TreeVisitor;
24+
import org.openrewrite.gradle.IsBuildGradle;
25+
import org.openrewrite.java.JavaVisitor;
26+
import org.openrewrite.java.tree.Expression;
27+
import org.openrewrite.java.tree.J;
28+
29+
@Value
30+
@EqualsAndHashCode(callSuper = false)
31+
public class UseMainClassPropertyForApplication extends Recipe {
32+
33+
private static final String IN_APPLICATION = "IN_APPLICATION";
34+
35+
String displayName = "Use `mainClass` instead of `mainClassName` in the `application` block";
36+
37+
String description = "The `mainClassName` property on the `application` extension was deprecated in Gradle 6.4 and removed in Gradle 9.0. " +
38+
"Use the `mainClass` property instead. " +
39+
"See the [Gradle upgrade guide](https://docs.gradle.org/9.0.0/userguide/upgrading_major_version_9.html) for more information.";
40+
41+
@Override
42+
public TreeVisitor<?, ExecutionContext> getVisitor() {
43+
return Preconditions.check(new IsBuildGradle<>(), new JavaVisitor<ExecutionContext>() {
44+
@Override
45+
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
46+
if ("application".equals(method.getSimpleName())) {
47+
getCursor().putMessage(IN_APPLICATION, true);
48+
}
49+
return super.visitMethodInvocation(method, ctx);
50+
}
51+
52+
@Override
53+
public J.Assignment visitAssignment(J.Assignment assignment, ExecutionContext ctx) {
54+
if (getCursor().getNearestMessage(IN_APPLICATION) == null) {
55+
return assignment;
56+
}
57+
Expression variable = assignment.getVariable();
58+
if (variable instanceof J.Identifier) {
59+
J.Identifier id = (J.Identifier) variable;
60+
if ("mainClassName".equals(id.getSimpleName())) {
61+
return assignment.withVariable(id.withSimpleName("mainClass"));
62+
}
63+
} else if (variable instanceof J.FieldAccess) {
64+
J.FieldAccess fieldAccess = (J.FieldAccess) variable;
65+
if ("mainClassName".equals(fieldAccess.getSimpleName())) {
66+
return assignment.withVariable(
67+
fieldAccess.withName(fieldAccess.getName().withSimpleName("mainClass"))
68+
);
69+
}
70+
}
71+
return assignment;
72+
}
73+
});
74+
}
75+
}

rewrite-gradle/src/main/resources/META-INF/rewrite/gradle-9.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ recipeList:
2525
addIfMissing: false
2626
# Map notation has been deprecated in 9.1+
2727
- org.openrewrite.gradle.DependencyUseStringNotation
28-
- org.openrewrite.gradle.gradle9.UseMainClassProperty
28+
- org.openrewrite.gradle.gradle9.UseMainClassProperty
29+
- org.openrewrite.gradle.gradle9.UseMainClassPropertyForApplication
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2026 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.gradle.gradle9;
17+
18+
import org.junit.jupiter.api.Nested;
19+
import org.junit.jupiter.api.Test;
20+
import org.openrewrite.DocumentExample;
21+
import org.openrewrite.test.RecipeSpec;
22+
import org.openrewrite.test.RewriteTest;
23+
24+
import static org.openrewrite.gradle.Assertions.buildGradle;
25+
import static org.openrewrite.gradle.Assertions.buildGradleKts;
26+
27+
class UseMainClassPropertyForApplicationTest implements RewriteTest {
28+
29+
@Override
30+
public void defaults(RecipeSpec spec) {
31+
spec.recipe(new UseMainClassPropertyForApplication());
32+
}
33+
34+
@DocumentExample
35+
@Test
36+
void mainClassNameInApplicationBlock() {
37+
rewriteRun(
38+
buildGradle(
39+
"""
40+
plugins {
41+
id 'application'
42+
}
43+
44+
application {
45+
mainClassName = "com.example.AppMain"
46+
}
47+
""",
48+
"""
49+
plugins {
50+
id 'application'
51+
}
52+
53+
application {
54+
mainClass = "com.example.AppMain"
55+
}
56+
"""
57+
)
58+
);
59+
}
60+
61+
@Test
62+
void mainClassNameInApplicationBlockKotlinDsl() {
63+
rewriteRun(
64+
buildGradleKts(
65+
"""
66+
plugins {
67+
application
68+
}
69+
70+
application {
71+
mainClassName = "com.example.AppMain"
72+
}
73+
""",
74+
"""
75+
plugins {
76+
application
77+
}
78+
79+
application {
80+
mainClass = "com.example.AppMain"
81+
}
82+
"""
83+
)
84+
);
85+
}
86+
87+
@Nested
88+
class NoChange {
89+
@Test
90+
void noChangeWhenAlreadyMigrated() {
91+
rewriteRun(
92+
buildGradle(
93+
"""
94+
plugins {
95+
id 'application'
96+
}
97+
98+
application {
99+
mainClass = "com.example.AppMain"
100+
}
101+
"""
102+
)
103+
);
104+
}
105+
106+
@Test
107+
void noChangeWhenAlreadyMigratedKotlinDsl() {
108+
rewriteRun(
109+
buildGradleKts(
110+
"""
111+
plugins {
112+
application
113+
}
114+
115+
application {
116+
mainClass = "com.example.AppMain"
117+
}
118+
"""
119+
)
120+
);
121+
}
122+
123+
@Test
124+
void noChangeOutsideApplicationBlock() {
125+
rewriteRun(
126+
buildGradle(
127+
"""
128+
plugins {
129+
id 'java'
130+
}
131+
132+
ext {
133+
mainClassName = "com.example.AppMain"
134+
}
135+
"""
136+
)
137+
);
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)