diff --git a/src/main/java/org/openrewrite/java/migrate/lang/UseVarKeyword.java b/src/main/java/org/openrewrite/java/migrate/lang/UseVarKeyword.java index dc62f8c9ac..ef22dce1ea 100644 --- a/src/main/java/org/openrewrite/java/migrate/lang/UseVarKeyword.java +++ b/src/main/java/org/openrewrite/java/migrate/lang/UseVarKeyword.java @@ -68,13 +68,23 @@ protected TreeVisitor 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()); - if (isOutsideMethod || isMethodParameter) return vd; + boolean isOutsideInitializer = !determineIfOutsideInitializer(this.getCursor(), false); + if ((isOutsideMethod && isOutsideInitializer) || isMethodParameter) return vd; TypeTree typeExpression = vd.getTypeExpression(); boolean isByteVariable = typeExpression instanceof J.Primitive && BYTE_TYPE.equals(typeExpression.getType()); @@ -90,12 +100,28 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m boolean isNullAssigment = initializer instanceof J.Literal && isNull(((J.Literal) initializer).getValue()); boolean alreadyUseVar = typeExpression instanceof J.Identifier && "var".equals(((J.Identifier) typeExpression).getSimpleName()); boolean isGeneric = typeExpression instanceof J.ParameterizedType; // todo implement generics! - if (alreadyUseVar || isDeclarationOnly || isNullAssigment || isGeneric) return vd; + boolean useTernary = initializer instanceof J.Ternary; + if (alreadyUseVar || isDeclarationOnly || isNullAssigment || isGeneric || useTernary) return vd; J.VariableDeclarations result = transformToVar(vd); return result; } + private boolean determineIfOutsideInitializer(Cursor cursor, boolean childWasBlock) { + Object currentStatement = cursor.getValue(); + + 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 isBlock = currentStatement instanceof J.Block; + return determineIfOutsideInitializer(parentStatement, isBlock); + } + private boolean determineIfMethodParameter(@NotNull J.VariableDeclarations vd, @NotNull Cursor cursor) { J.MethodDeclaration methodDeclaration = cursor.firstEnclosing(J.MethodDeclaration.class); return nonNull(methodDeclaration) && methodDeclaration.getParameters().contains(vd); diff --git a/src/test/java/org/openrewrite/java/migrate/lang/UseVarKeywordTest.java b/src/test/java/org/openrewrite/java/migrate/lang/UseVarKeywordTest.java index a1049e89b1..47461754b0 100644 --- a/src/test/java/org/openrewrite/java/migrate/lang/UseVarKeywordTest.java +++ b/src/test/java/org/openrewrite/java/migrate/lang/UseVarKeywordTest.java @@ -133,31 +133,117 @@ void m() { @Nested class Objects { - @Test - void inMethodBody() { - //language=java - rewriteRun( - version( - java(""" - package com.example.app; - - class A { - void m() { - Object o = new Object(); - } - } - """, """ - package com.example.app; - - class A { - void m() { - var o = new Object(); - } - } - """), - 10 - ) - ); + + @Nested + class Applicable { + @Test + void inMethodBody() { + //language=java + rewriteRun( + version( + java(""" + package com.example.app; + + class A { + void m() { + Object o = new Object(); + } + } + """, """ + package com.example.app; + + class A { + void m() { + var o = new Object(); + } + } + """), + 10 + ) + ); + } + + @Test + @Disabled("Not yet implemented") + void withTernary() { + //language=java + rewriteRun( + version( + java(""" + package com.example.app; + + class A { + void m() { + String o = true ? "isTrue" : "Test"; + } + } + """, """ + package com.example.app; + + class A { + void m() { + var o = true ? "isTrue" : "Test"; + } + } + """), + 10 + ) + ); + } + + @Test + void inStaticInitializer() { + //language=java + rewriteRun( + version( + java(""" + package com.example.app; + + class A { + static { + Object o = new Object(); + } + } + """, """ + package com.example.app; + + class A { + static { + var o = new Object(); + } + } + """), + 10 + ) + ); + } + + @Test + void inInstanceInitializer() { + //language=java + rewriteRun( + version( + java(""" + package com.example.app; + + class A { + { + Object o = new Object(); + } + } + """, """ + package com.example.app; + + class A { + { + var o = new Object(); + } + } + """), + 10 + ) + ); + } } @Nested