Skip to content

Commit f37ee62

Browse files
Rename variables if the name matches class name (#5454)
* Rename variables if the name matches class name * Prevent variable name conflicts; support unicode characters * Fix tests in rewrite-kotlin * Add test verifying that random variables with matching name are not renamed * Use 𐐅/𐐭 instead of Ą/ą in test since Ą is in BMP * Revert unicode characters handling in decapitalize method as it seems to be a broader issue * Follow naming convention for ctx * Move all logic into `visitVariable` and leverage `RenameVariable` * Swap order of checks * No changes to variable name without change to type * Update cursor before `generateVariableName` to avoid conflicts * Do not expect Kotlin changes just yet --------- Co-authored-by: Tim te Beek <[email protected]>
1 parent 31e3c63 commit f37ee62

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

rewrite-java-test/src/test/java/org/openrewrite/java/ChangeTypeTest.java

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,8 +1592,8 @@ public A1 method(A1 a1) {
15921592
import a.A2;
15931593
15941594
public class Example {
1595-
public A2 method(A2 a1) {
1596-
return a1;
1595+
public A2 method(A2 a2) {
1596+
return a2;
15971597
}
15981598
}
15991599
"""
@@ -1630,6 +1630,101 @@ public class Test {
16301630
);
16311631
}
16321632

1633+
@Test
1634+
void doNotRenameRandomVariablesMatchingClassName() {
1635+
rewriteRun(
1636+
spec -> spec.recipe(new ChangeType("a.A1", "a.A2", false)),
1637+
java(
1638+
"""
1639+
package a;
1640+
public class A1 {
1641+
}
1642+
""",
1643+
"""
1644+
package a;
1645+
public class A2 {
1646+
}
1647+
"""
1648+
),
1649+
java(
1650+
"""
1651+
package org.foo;
1652+
1653+
import a.A1;
1654+
1655+
public class Example {
1656+
public String method(A1 a, String a1) {
1657+
return a1;
1658+
}
1659+
}
1660+
""",
1661+
"""
1662+
package org.foo;
1663+
1664+
import a.A2;
1665+
1666+
public class Example {
1667+
public String method(A2 a, String a1) {
1668+
return a1;
1669+
}
1670+
}
1671+
"""
1672+
)
1673+
);
1674+
}
1675+
1676+
@Test
1677+
void noChangeToVariableNameWithoutChangeToType() {
1678+
rewriteRun(
1679+
spec -> spec.recipe(new ChangeType("a.A1", "a.A2", true)),
1680+
java(
1681+
"""
1682+
package a;
1683+
public class A1 {
1684+
}
1685+
"""
1686+
),
1687+
java(
1688+
"""
1689+
package a;
1690+
public class A2 {
1691+
}
1692+
"""
1693+
),
1694+
java(
1695+
"""
1696+
package org.foo;
1697+
1698+
import a.A1;
1699+
import a.A2;
1700+
1701+
public class Example {
1702+
public A1 method1(A1 a1) {
1703+
return a1;
1704+
}
1705+
public A2 method2(A2 a1) {
1706+
return a1; // Unchanged
1707+
}
1708+
}
1709+
""",
1710+
"""
1711+
package org.foo;
1712+
1713+
import a.A2;
1714+
1715+
public class Example {
1716+
public A2 method1(A2 a2) {
1717+
return a2;
1718+
}
1719+
public A2 method2(A2 a1) {
1720+
return a1; // Unchanged
1721+
}
1722+
}
1723+
"""
1724+
)
1725+
);
1726+
}
1727+
16331728
@Test
16341729
void updateVariableType() {
16351730
rewriteRun(

rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.jspecify.annotations.Nullable;
2121
import org.openrewrite.*;
2222
import org.openrewrite.internal.ListUtils;
23+
import org.openrewrite.java.VariableNameUtils.GenerationStrategy;
2324
import org.openrewrite.java.search.UsesType;
2425
import org.openrewrite.java.tree.*;
2526
import org.openrewrite.marker.Markers;
@@ -387,6 +388,26 @@ public J visitIdentifier(J.Identifier ident, ExecutionContext ctx) {
387388
return visitAndCast(ident, ctx, super::visitIdentifier);
388389
}
389390

391+
@Override
392+
public J.VariableDeclarations.NamedVariable visitVariable(J.VariableDeclarations.NamedVariable variable, ExecutionContext ctx) {
393+
J.VariableDeclarations.NamedVariable v = (J.VariableDeclarations.NamedVariable) super.visitVariable(variable, ctx);
394+
if (v != variable) {
395+
if (v.getSimpleName().equals(decapitalize(originalType.getClassName()))) {
396+
if (targetType instanceof JavaType.FullyQualified) {
397+
if (v.getVariableType() != null && TypeUtils.isOfType(targetType, v.getVariableType().getType())) {
398+
String newName = VariableNameUtils.generateVariableName(
399+
decapitalize(((JavaType.FullyQualified) targetType).getClassName()),
400+
updateCursor(v),
401+
GenerationStrategy.INCREMENT_NUMBER
402+
);
403+
doAfterVisit(new RenameVariable<>(v, newName));
404+
}
405+
}
406+
}
407+
}
408+
return v;
409+
}
410+
390411
@Override
391412
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
392413
if (method.getMethodType() != null && method.getMethodType().hasFlags(Flag.Static)) {
@@ -778,4 +799,11 @@ private static boolean hasSameFQN(J.Import import_, JavaType targetType) {
778799

779800
return fqn != null && fqn.equals(curFqn);
780801
}
802+
803+
private static String decapitalize(@Nullable String string) {
804+
if (string != null && !string.isEmpty()) {
805+
return Character.toLowerCase(string.charAt(0)) + string.substring(1);
806+
}
807+
return "";
808+
}
781809
}

0 commit comments

Comments
 (0)