Skip to content

Commit

Permalink
replace
Browse files Browse the repository at this point in the history
  • Loading branch information
MBoegers committed May 24, 2023
1 parent f1b73f8 commit 55a3d4b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 32 deletions.
52 changes: 21 additions & 31 deletions src/main/java/org/openrewrite/java/migrate/lang/UseVarKeyword.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.search.HasJavaVersion;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.TypeTree;
import org.openrewrite.java.tree.*;

import java.time.Duration;

Expand Down Expand Up @@ -68,22 +65,13 @@ protected TreeVisitor<?, ExecutionContext> getVisitor() {
private final JavaTemplate template = JavaTemplate.builder(this::getCursor, "var #{} = #{any()}")
.javaParser(JavaParser.fromJavaVersion()).build();


@Override
public J visitForEachControl(J.ForEachLoop.Control control, ExecutionContext executionContext) {
// für enhanced for-Loops wäre hier der korrekter punkt.
// es gelten dieselben Dinge für primitives, null und Generics
// ob wir am richtigen Ort sind muss nicht geprüft werden; ebenso single und pure
return super.visitForEachControl(control, executionContext);
}

@Override
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext executionContext) {
J.VariableDeclarations vd = (J.VariableDeclarations) super.visitVariableDeclarations(multiVariable, executionContext);

boolean isOutsideMethod = !determineIfIsInsideMethod(this.getCursor());
boolean isMethodParameter = determineIfMethodParameter(vd, this.getCursor());
boolean isOutsideInitializer = !determineIfOutsideInitializer(this.getCursor(), false);
boolean isOutsideInitializer = !determineInsideInitializer(this.getCursor(), 0);
if ((isOutsideMethod && isOutsideInitializer) || isMethodParameter) return vd;

TypeTree typeExpression = vd.getTypeExpression();
Expand All @@ -110,19 +98,24 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m
return transformToVar(vd);
}

private boolean determineIfOutsideInitializer(Cursor cursor, boolean childWasBlock) {
private boolean determineInsideInitializer(@NotNull Cursor cursor, int nestedBlockLevel) {
if (Cursor.ROOT_VALUE.equals(cursor.getValue())) {
return false;
}
Object currentStatement = cursor.getValue();

// initializer blocks are blocks inside the class definition block, therefor a nesting of 2 is mandatory
boolean isClassDeclaration = currentStatement instanceof J.ClassDeclaration;
boolean classFollowedByBlock = childWasBlock && isClassDeclaration;
if (classFollowedByBlock) return true;

Cursor parentStatement = cursor.getParent();
boolean cannotClimbUpFurther = isNull(parentStatement);
if (cannotClimbUpFurther) return false;
boolean followedByTwoBlock = nestedBlockLevel >= 2;
if (isClassDeclaration && followedByTwoBlock) return true;

// count direct block nesting (block containing a block), but ignore paddings
boolean isBlock = currentStatement instanceof J.Block;
return determineIfOutsideInitializer(parentStatement, isBlock);
boolean isNoPadding = !(currentStatement instanceof JRightPadded);
if (isBlock) nestedBlockLevel += 1;
else if (isNoPadding) nestedBlockLevel = 0;

return determineInsideInitializer(requireNonNull(cursor.getParent()), nestedBlockLevel);
}

private boolean determineIfMethodParameter(@NotNull J.VariableDeclarations vd, @NotNull Cursor cursor) {
Expand All @@ -137,12 +130,13 @@ private boolean determineIfMethodParameter(@NotNull J.VariableDeclarations vd, @
private boolean determineIfIsInsideMethod(@NotNull Cursor cursor) {
Object current = cursor.getValue();

if (Cursor.ROOT_VALUE.equals(current)) return false; // we are at the top, no further climbing needed
if (current instanceof J.ClassDeclaration)
return false; // after a ClassDeclaration we left the scope of search
if (current instanceof J.MethodDeclaration) return true; // we found the MethodDeclaration
boolean atRoot = Cursor.ROOT_VALUE.equals(current);
boolean atClassDeclaration = current instanceof J.ClassDeclaration;
boolean atMethodDeclaration = current instanceof J.MethodDeclaration;

return determineIfIsInsideMethod(requireNonNull(cursor.getParent())); // climb up
if (atRoot || atClassDeclaration) return false;
if (atMethodDeclaration) return true;
return determineIfIsInsideMethod(requireNonNull(cursor.getParent()));
}

@NotNull
Expand All @@ -152,10 +146,6 @@ private J.VariableDeclarations transformToVar(@NotNull J.VariableDeclarations vd

if (initializer instanceof J.Literal) {
initializer = expandWithPrimitivTypeHint(vd, initializer);
} else if(initializer instanceof J.MethodInvocation && nonNull(((J.MethodInvocation) initializer).getTypeParameters())) {
initializer = initializer;
} else if(initializer instanceof J.NewClass && ((J.NewClass) initializer).getClazz() instanceof J.ParameterizedType) {

}
return vd.withTemplate(template, vd.getCoordinates().replace(), simpleName, initializer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,35 @@ void m() {
);
}

@Test
void reassignment() {
//language=java
rewriteRun(
version(
java("""
package com.example.app;
class A {
Object o = new Object();
void m() {
Object innerO = o;
}
}
""", """
package com.example.app;
class A {
Object o = new Object();
void m() {
var innerO = o;
}
}
"""),
10
)
);
}

@Test
@Disabled("this should be possible, but it needs very hard type inference")
void withTernary() {
Expand Down Expand Up @@ -462,7 +491,7 @@ void asField() {
package com.example.app;
class A {
Object o;
Object o = new Object();
Object m() {
return o;
}
Expand Down

0 comments on commit 55a3d4b

Please sign in to comment.