Skip to content

Commit

Permalink
UseVar must not modify fields of anonymous subclasses
Browse files Browse the repository at this point in the history
Fixes: #241
  • Loading branch information
knutwannheden committed Jun 19, 2023
1 parent ff4d3dc commit 688ce47
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
*/
package org.openrewrite.java.migrate.lang.var;

import static java.util.Objects.requireNonNull;

import org.openrewrite.Cursor;
import org.openrewrite.java.tree.*;

import static java.util.Objects.requireNonNull;

final class DeclarationCheck {

private DeclarationCheck() {
Expand All @@ -37,14 +37,11 @@ private DeclarationCheck() {
* @return true if var is applicable in general
*/
public static boolean isVarApplicable(Cursor cursor, J.VariableDeclarations vd) {
boolean isMethodParameter = DeclarationCheck.isMethodParameter(vd, cursor);
boolean isMultiVarDefinition = !DeclarationCheck.isSingleVariableDefinition(vd);
boolean useTernary = DeclarationCheck.initializedByTernary(vd);
if (isMethodParameter || isMultiVarDefinition || useTernary) return false;

boolean isInsideMethod = DeclarationCheck.isInsideMethod(cursor);
boolean isInsideInitializer = DeclarationCheck.isInsideInitializer(cursor, 0);
return isInsideMethod || isInsideInitializer;
if (isField(vd, cursor) || isMethodParameter(vd, cursor) || !isSingleVariableDefinition(vd) || initializedByTernary(vd)) {
return false;
}

return isInsideMethod(cursor) || isInsideInitializer(cursor, 0);
}

/**
Expand Down Expand Up @@ -140,6 +137,15 @@ private static boolean isInsideMethod(Cursor cursor) {
return isNotRoot && isNotClassDeclaration && isMethodDeclaration;
}

private static boolean isField(J.VariableDeclarations vd, Cursor cursor) {
Cursor parent = cursor.getParentTreeCursor();
if (parent.getParent() == null) {
return false;
}
Cursor grandparent = parent.getParentTreeCursor();
return parent.getValue() instanceof J.Block && (grandparent.getValue() instanceof J.ClassDeclaration || grandparent.getValue() instanceof J.NewClass);
}

/**
* Determine if the variable declaration at hand is part of a method declaration
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static final class UseVarForObjectVisitor extends JavaIsoVisitor<ExecutionContex
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations vd, ExecutionContext ctx) {
vd = super.visitVariableDeclarations(vd, ctx);

boolean isGeneralApplicable = DeclarationCheck.isVarApplicable(this.getCursor(), vd);
boolean isGeneralApplicable = DeclarationCheck.isVarApplicable(getCursor(), vd);
if (!isGeneralApplicable) return vd;

boolean isPrimitive = DeclarationCheck.isPrimitive(vd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
import org.openrewrite.DocumentExample;
import org.openrewrite.test.RecipeSpec;

import static org.openrewrite.java.Assertions.*;
import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.java.Assertions.javaVersion;

class UseVarForObjectsTest extends VarBaseTest {

Expand Down Expand Up @@ -184,6 +185,23 @@ class A {

@Nested
class NotApplicable {
@Test
void fieldInAnonymousSubclass() {
//language=java
rewriteRun(
java("""
class A {
void m() {
new Object() {
private final Object o1 = new Object();
};
}
}
"""
)
);
}

@Test
void asParameter() {
//language=java
Expand Down

0 comments on commit 688ce47

Please sign in to comment.