diff --git a/src/main/java/org/openrewrite/staticanalysis/NeedBraces.java b/src/main/java/org/openrewrite/staticanalysis/NeedBraces.java index b58f916ef1..7c179d574b 100644 --- a/src/main/java/org/openrewrite/staticanalysis/NeedBraces.java +++ b/src/main/java/org/openrewrite/staticanalysis/NeedBraces.java @@ -21,6 +21,8 @@ import org.openrewrite.java.style.Checkstyle; import org.openrewrite.java.style.NeedBracesStyle; import org.openrewrite.java.tree.*; +import org.openrewrite.kotlin.KotlinIsoVisitor; +import org.openrewrite.kotlin.tree.K; import org.openrewrite.marker.Markers; import java.time.Duration; @@ -52,10 +54,22 @@ public Duration getEstimatedEffortPerOccurrence() { @Override public TreeVisitor getVisitor() { - return new NeedBracesVisitor(); + + return new TreeVisitor() { + @Override + public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx, Cursor parent) { + if (tree instanceof J.CompilationUnit) { + return new NeedBracesJavaVisitor().visit(tree, ctx); + } else if (tree instanceof K.CompilationUnit) { + return new NeedBracesKotlinVisitor().visit(tree, ctx); + } + + return tree; + } + }; } - private static class NeedBracesVisitor extends JavaIsoVisitor { + private static class NeedBracesJavaVisitor extends JavaIsoVisitor { NeedBracesStyle needBracesStyle; /** @@ -152,6 +166,9 @@ public J.ForLoop visitForLoop(J.ForLoop forLoop, ExecutionContext ctx) { } return elem; } + } + private static class NeedBracesKotlinVisitor extends KotlinIsoVisitor { + // Implement ME. Hold on to transformation on Kotlin files until AutoFormat supports Kotlin well } } diff --git a/src/main/java/org/openrewrite/staticanalysis/ReplaceLambdaWithMethodReference.java b/src/main/java/org/openrewrite/staticanalysis/ReplaceLambdaWithMethodReference.java index dfd3f0a0c6..7ce596b657 100644 --- a/src/main/java/org/openrewrite/staticanalysis/ReplaceLambdaWithMethodReference.java +++ b/src/main/java/org/openrewrite/staticanalysis/ReplaceLambdaWithMethodReference.java @@ -15,14 +15,14 @@ */ package org.openrewrite.staticanalysis; -import org.openrewrite.Cursor; -import org.openrewrite.ExecutionContext; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; +import org.openrewrite.*; +import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.ShortenFullyQualifiedTypeReferences; import org.openrewrite.java.tree.*; +import org.openrewrite.kotlin.KotlinVisitor; +import org.openrewrite.kotlin.tree.K; import java.time.Duration; import java.util.*; @@ -54,16 +54,29 @@ public Duration getEstimatedEffortPerOccurrence() { @Override public TreeVisitor getVisitor() { - return new JavaVisitor() { + return new TreeVisitor() { @Override + public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx, Cursor parent) { + if (tree instanceof J.CompilationUnit) { + return new ReplaceLambdaWithMethodReferenceJavaVisitor().visit(tree, ctx); + } else if (tree instanceof K.CompilationUnit) { + return new ReplaceLambdaWithMethodReferenceKotlinVisitor().visit(tree, ctx); + } + return tree; + } + }; + } + + private static class ReplaceLambdaWithMethodReferenceKotlinVisitor extends KotlinVisitor { + // Implement Me + } + + private static class ReplaceLambdaWithMethodReferenceJavaVisitor extends JavaVisitor { + @Override public J visitLambda(J.Lambda lambda, ExecutionContext executionContext) { J.Lambda l = (J.Lambda) super.visitLambda(lambda, executionContext); updateCursor(l); - if (TypeUtils.isOfClassType(lambda.getType(), "groovy.lang.Closure")) { - return l; - } - String code = ""; J body = l.getBody(); if (body instanceof J.Block && ((J.Block) body).getStatements().size() == 1) { @@ -236,9 +249,7 @@ private boolean isNullCheck(J j1, J j2) { return j1 instanceof J.Identifier && j2 instanceof J.Literal && "null".equals(((J.Literal) j2).getValueSource()); } - }; - - } + } private static boolean isAMethodInvocationArgument(J.Lambda lambda, Cursor cursor) { Cursor parent = cursor.dropParentUntil(p -> p instanceof J.MethodInvocation || p instanceof J.CompilationUnit); diff --git a/src/test/java/org/openrewrite/staticanalysis/kotlin/NeedBracesTest.java b/src/test/java/org/openrewrite/staticanalysis/kotlin/NeedBracesTest.java new file mode 100644 index 0000000000..40a81af83b --- /dev/null +++ b/src/test/java/org/openrewrite/staticanalysis/kotlin/NeedBracesTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.staticanalysis.kotlin; + +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ExpectedToFail; +import org.openrewrite.staticanalysis.NeedBraces; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.kotlin.Assertions.kotlin; + +class NeedBracesTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new NeedBraces()); + } + + @ExpectedToFail("Kotlin version visitor to be implemented") + @Test + void addBracesForIfBranch() { + rewriteRun( + kotlin( + """ + fun getSymbol(num : Int) : String { + if (num > 0) return "+" + + return "-" + } + """, + """ + fun getSymbol(num : Int) : String { + if (num > 0) { + return "+" + } + + return "-" + } + """ + ) + ); + } + + @ExpectedToFail("Kotlin version visitor to be implemented") + @Test + void addBracesForElseBranch() { + rewriteRun( + kotlin( + """ + fun getSymbol(num : Int) : String { + return if (num > 0) + "+" + else "-" + } + """, + """ + fun getSymbol(num : Int) : String { + return if (num > 0) { + "+" + } else { + "-" + } + } + """ + ) + ); + } + + @Test + void doNotChangeForArguments() { + rewriteRun( + kotlin( + """ + fun run(foo: String, bar: String) {} + var x = run( if (true) "" else "", + if (true) "" else "") + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/staticanalysis/kotlin/ReplaceLambdaWithMethodReferenceTest.java b/src/test/java/org/openrewrite/staticanalysis/kotlin/ReplaceLambdaWithMethodReferenceTest.java new file mode 100644 index 0000000000..05ed6eac28 --- /dev/null +++ b/src/test/java/org/openrewrite/staticanalysis/kotlin/ReplaceLambdaWithMethodReferenceTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.staticanalysis.kotlin; + +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ExpectedToFail; +import org.openrewrite.staticanalysis.ReplaceLambdaWithMethodReference; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + + +import static org.openrewrite.kotlin.Assertions.kotlin; + +class ReplaceLambdaWithMethodReferenceTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new ReplaceLambdaWithMethodReference()); + } + + @ExpectedToFail("Kotlin visitor to be implemented") + @Test + void toQualifiedMethodReference() { + rewriteRun( + kotlin( + """ + interface Pet { + fun move() { + } + } + + class Cat : Pet { + override fun move() { + println("Cat is moving") + } + } + + class Dog : Pet { + override fun move() { + println("Dog is moving") + } + } + """ + ), + kotlin( + """ + fun main() { + val pets = listOf(Cat(), Dog()) + pets.forEach { it.move() } + } + """, + """ + fun main() { + val pets = listOf(Cat(), Dog()) + pets.forEach ( Pet::move ) + } + """ + ) + ); + } + + @ExpectedToFail("Kotlin visitor to be implemented") + @Test + void toUnqualifiedMethodReference() { + rewriteRun( + kotlin( + """ + fun isEven(number: Int): Boolean { + return number % 2 == 0 + } + """ + ), + kotlin( + """ + val numbers = listOf(1, 2, 3, 4, 5) + val evenNumbers = numbers.filter{isEven(it)} + """ + , + """ + val numbers = listOf(1, 2, 3, 4, 5) + val evenNumbers = numbers.filter(::isEven) + """ + ) + ); + } + +}