Skip to content

Commit 461609f

Browse files
authored
Rename _ identifier to __ for Java ≤ 8 source files (#1063)
* Rename `_` identifier to `__` for Java ≤ 8 source files In Java 9+, `_` became a reserved keyword causing compile errors. This recipe renames single-underscore identifiers to double-underscore as a prerequisite migration step for projects upgrading from Java 8. Closes moderneinc/customer-requests#2221 * Extract package-private RenameIdentifierVisitor for reuse in tests Addresses review feedback: the visitor logic is now shared between the recipe and the test setup recipe via RenameIdentifierVisitor(oldName, newName). * Move RenameIdentifierVisitor to static nested class Inline the visitor as a static nested class of RenameUnderscoreIdentifier instead of a separate top-level file. * Regenerate recipes.csv * Use @requiredargsconstructor on RenameIdentifierVisitor * Use import for @requiredargsconstructor * Use @value on RenameIdentifierVisitor * Remove redundant private final modifiers on @value fields
1 parent 634e7d9 commit 461609f

4 files changed

Lines changed: 450 additions & 13 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Moderne Source Available License (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://docs.moderne.io/licensing/moderne-source-available-license
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.migrate.lang;
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.java.JavaIsoVisitor;
25+
import org.openrewrite.java.RenameVariable;
26+
import org.openrewrite.java.search.UsesJavaVersion;
27+
import org.openrewrite.java.tree.J;
28+
import org.openrewrite.java.tree.JavaType;
29+
30+
@EqualsAndHashCode(callSuper = false)
31+
@Value
32+
public class RenameUnderscoreIdentifier extends Recipe {
33+
34+
String displayName = "Rename `_` identifier to `__`";
35+
36+
String description = "Renames single-underscore identifiers to double-underscore " +
37+
"in Java source files with source compatibility of Java 8 or below. " +
38+
"In Java 9+, `_` is a reserved keyword and causes a compile error.";
39+
40+
@Override
41+
public TreeVisitor<?, ExecutionContext> getVisitor() {
42+
return Preconditions.check(
43+
new UsesJavaVersion<>(1, 8),
44+
new RenameIdentifierVisitor("_", "__")
45+
);
46+
}
47+
48+
@Value
49+
@EqualsAndHashCode(callSuper = false)
50+
static class RenameIdentifierVisitor extends JavaIsoVisitor<ExecutionContext> {
51+
52+
String oldName;
53+
String newName;
54+
55+
@Override
56+
public J.VariableDeclarations visitVariableDeclarations(
57+
J.VariableDeclarations multiVariable, ExecutionContext ctx) {
58+
for (J.VariableDeclarations.NamedVariable v : multiVariable.getVariables()) {
59+
if (oldName.equals(v.getSimpleName())) {
60+
doAfterVisit(new RenameVariable<>(v, newName));
61+
}
62+
}
63+
return super.visitVariableDeclarations(multiVariable, ctx);
64+
}
65+
66+
@Override
67+
public J.MethodDeclaration visitMethodDeclaration(
68+
J.MethodDeclaration method, ExecutionContext ctx) {
69+
method = super.visitMethodDeclaration(method, ctx);
70+
if (oldName.equals(method.getSimpleName())) {
71+
JavaType.Method type = method.getMethodType();
72+
if (type != null) {
73+
type = type.withName(newName);
74+
}
75+
method = method.withName(method.getName().withSimpleName(newName)
76+
.withType(type))
77+
.withMethodType(type);
78+
}
79+
return method;
80+
}
81+
82+
@Override
83+
public J.MethodInvocation visitMethodInvocation(
84+
J.MethodInvocation method, ExecutionContext ctx) {
85+
method = super.visitMethodInvocation(method, ctx);
86+
if (oldName.equals(method.getSimpleName())) {
87+
JavaType.Method type = method.getMethodType();
88+
if (type != null) {
89+
type = type.withName(newName);
90+
}
91+
method = method.withName(method.getName().withSimpleName(newName)
92+
.withType(type))
93+
.withMethodType(type);
94+
}
95+
return method;
96+
}
97+
98+
@Override
99+
public J.MemberReference visitMemberReference(
100+
J.MemberReference memberRef, ExecutionContext ctx) {
101+
memberRef = super.visitMemberReference(memberRef, ctx);
102+
if (oldName.equals(memberRef.getReference().getSimpleName())) {
103+
JavaType.Method type = memberRef.getMethodType();
104+
if (type != null) {
105+
type = type.withName(newName);
106+
}
107+
memberRef = memberRef.withReference(memberRef.getReference().withSimpleName(newName))
108+
.withMethodType(type);
109+
}
110+
return memberRef;
111+
}
112+
113+
@Override
114+
public J.ClassDeclaration visitClassDeclaration(
115+
J.ClassDeclaration classDecl, ExecutionContext ctx) {
116+
classDecl = super.visitClassDeclaration(classDecl, ctx);
117+
if (oldName.equals(classDecl.getSimpleName())) {
118+
classDecl = classDecl.withName(classDecl.getName().withSimpleName(newName));
119+
}
120+
return classDecl;
121+
}
122+
}
123+
}

src/main/resources/META-INF/rewrite/java-version-11.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ preconditions:
3434
- org.openrewrite.Singleton
3535
recipeList:
3636
- org.openrewrite.java.migrate.UpgradeToJava8
37+
- org.openrewrite.java.migrate.lang.RenameUnderscoreIdentifier
3738
- org.openrewrite.java.migrate.UseJavaUtilBase64
3839
- org.openrewrite.java.migrate.CastArraysAsListToList
3940
# Add an explicit JAXB/JAX-WS runtime and upgrade the dependencies to Jakarta EE 8

0 commit comments

Comments
 (0)