From ea27d85081c8b0be04bd04a1d22e8c181db0b294 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Fri, 18 Aug 2023 15:19:50 +0200 Subject: [PATCH 1/6] Proof of concept for `@Matches` annotation --- build.gradle.kts | 1 + .../template/RefasterTemplateProcessor.java | 12 +++ .../template/internal/ImportDetector.java | 6 ++ .../template/MethodInvocationMatcher.java | 26 +++++++ .../RefasterTemplateProcessorTest.java | 1 + src/test/resources/recipes/Matching.java | 22 ++++++ .../resources/recipes/MatchingRecipes.java | 73 +++++++++++++++++++ 7 files changed, 141 insertions(+) create mode 100644 src/test/java/org/openrewrite/java/template/MethodInvocationMatcher.java create mode 100644 src/test/resources/recipes/Matching.java create mode 100644 src/test/resources/recipes/MatchingRecipes.java diff --git a/build.gradle.kts b/build.gradle.kts index b27c3acf..1af155ff 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,6 +42,7 @@ dependencyCheck { } repositories { mavenCentral() + mavenLocal() } nexusPublishing { diff --git a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java index 746e0745..85f7b387 100644 --- a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java @@ -275,6 +275,18 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { recipe.append(" JavaTemplate.Matcher matcher;\n"); String predicate = befores.keySet().stream().map(b -> "(matcher = " + b + ".matcher(getCursor())).find()").collect(Collectors.joining(" || ")); recipe.append(" if (" + predicate + ") {\n"); + for (JCTree.JCAnnotation jcAnnotation : befores.entrySet().iterator().next().getValue().getParameters().get(0).getModifiers().getAnnotations()) { + String annotationType = ((JCTree.JCIdent) jcAnnotation.annotationType).sym.getQualifiedName().toString(); + if (annotationType.equals("org.openrewrite.java.template.NotMatches")) { + recipe.append(" if (new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) {\n"); + recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); + recipe.append(" }\n"); + } else if (annotationType.equals("org.openrewrite.java.template.Matches")) { + recipe.append(" if (!new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) {\n"); + recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); + recipe.append(" }\n"); + } + } Set beforeImports = imports.entrySet().stream() .filter(e -> descriptor.beforeTemplates.contains(e.getKey())) .map(Map.Entry::getValue) diff --git a/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java b/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java index 5fce897a..82fa3e98 100644 --- a/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java +++ b/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java @@ -57,6 +57,12 @@ public void scan(JCTree tree) { } } + // skip lhs of annotation assignments + if (tree instanceof JCTree.JCAssign) { + super.scan(((JCTree.JCAssign) tree).rhs); + return; + } + if (tree instanceof JCIdent) { if (tree.type == null || !(tree.type.tsym instanceof Symbol.ClassSymbol)) { return; diff --git a/src/test/java/org/openrewrite/java/template/MethodInvocationMatcher.java b/src/test/java/org/openrewrite/java/template/MethodInvocationMatcher.java new file mode 100644 index 00000000..44fdb80f --- /dev/null +++ b/src/test/java/org/openrewrite/java/template/MethodInvocationMatcher.java @@ -0,0 +1,26 @@ +/* + * 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.java.template; + +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; + +public class MethodInvocationMatcher implements Matcher { + @Override + public boolean matches(Expression expr) { + return expr instanceof J.MethodInvocation; + } +} diff --git a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java index c9597cb7..798a3554 100644 --- a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java +++ b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java @@ -56,6 +56,7 @@ void generateRecipe(String recipeName) { "ShouldSupportNestedClasses", "ShouldAddImports", "MultipleDereferences", + "Matching", }) void nestedRecipes(String recipeName) { Compilation compilation = javac() diff --git a/src/test/resources/recipes/Matching.java b/src/test/resources/recipes/Matching.java new file mode 100644 index 00000000..141a824a --- /dev/null +++ b/src/test/resources/recipes/Matching.java @@ -0,0 +1,22 @@ +package foo; + +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import org.openrewrite.java.template.MethodInvocationMatcher; +import org.openrewrite.java.template.NotMatches; + +public class Matching { + + public static class StringIsEmpty { + @BeforeTemplate + boolean before(@NotMatches(MethodInvocationMatcher.class) String s) { + return s.isEmpty(); + } + + @AfterTemplate + boolean after(String s) { + return s != null && s.length() == 0; + } + } + +} diff --git a/src/test/resources/recipes/MatchingRecipes.java b/src/test/resources/recipes/MatchingRecipes.java new file mode 100644 index 00000000..e7b48fc3 --- /dev/null +++ b/src/test/resources/recipes/MatchingRecipes.java @@ -0,0 +1,73 @@ +package foo; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.template.Primitive; +import org.openrewrite.java.tree.*; + +import java.util.Arrays; +import java.util.List; + +import org.openrewrite.java.template.MethodInvocationMatcher; + +public final class MatchingRecipes extends Recipe { + + @Override + public String getDisplayName() { + return "Refaster recipes for `foo.Matching`"; + } + + @Override + public String getDescription() { + return "Refaster template recipes for `foo.Matching`."; + } + + + @Override + public List getRecipeList() { + return Arrays.asList( + new StringIsEmptyRecipe() + ); + } + + public static class StringIsEmptyRecipe extends Recipe { + + @Override + public String getDisplayName() { + return "Refaster template `Matching.StringIsEmpty`"; + } + + @Override + public String getDescription() { + return "Recipe created for the following Refaster template:\n```java\npublic static class StringIsEmpty {\n \n @BeforeTemplate()\n boolean before(@NotMatches(value = MethodInvocationMatcher.class)\n String s) {\n return s.isEmpty();\n }\n \n @AfterTemplate()\n boolean after(String s) {\n return s != null && s.length() == 0;\n }\n}\n```\n."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaVisitor() { + final JavaTemplate before = JavaTemplate.compile(this, "before", (JavaTemplate.F1) (String s) -> s.isEmpty()).build(); + final JavaTemplate after = JavaTemplate.compile(this, "after", (String s) -> s != null && s.length() == 0).build(); + + @Override + public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { + JavaTemplate.Matcher matcher; + if ((matcher = before.matcher(getCursor())).find()) { + if (new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) { + return super.visitMethodInvocation(elem, ctx); + } + maybeRemoveImport("org.openrewrite.java.template.MethodInvocationMatcher"); + doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); + } + return super.visitMethodInvocation(elem, ctx); + } + + }; + } + } + +} From 4fbf6e8f96e9a1a38f9f16ea5c86c18396525baf Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Fri, 18 Aug 2023 15:29:51 +0200 Subject: [PATCH 2/6] Skip annotations and properly extract matcher from annotation --- .../java/template/RefasterTemplateProcessor.java | 6 ++++-- .../java/template/internal/ImportDetector.java | 5 ++--- src/test/resources/recipes/MatchingRecipes.java | 10 ++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java index 85f7b387..a1314820 100644 --- a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java @@ -278,11 +278,13 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { for (JCTree.JCAnnotation jcAnnotation : befores.entrySet().iterator().next().getValue().getParameters().get(0).getModifiers().getAnnotations()) { String annotationType = ((JCTree.JCIdent) jcAnnotation.annotationType).sym.getQualifiedName().toString(); if (annotationType.equals("org.openrewrite.java.template.NotMatches")) { - recipe.append(" if (new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) {\n"); + String matcher = ((JCTree.JCAssign) jcAnnotation.getArguments().get(0)).getExpression().type.getTypeArguments().get(0).tsym.getQualifiedName().toString(); + recipe.append(" if (new " + matcher + "().matches((Expression) matcher.parameter(0))) {\n"); recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); recipe.append(" }\n"); } else if (annotationType.equals("org.openrewrite.java.template.Matches")) { - recipe.append(" if (!new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) {\n"); + String matcher = ((JCTree.JCAssign) jcAnnotation.getArguments().get(0)).getExpression().type.getTypeArguments().get(0).tsym.getQualifiedName().toString(); + recipe.append(" if (!new " + matcher + "().matches((Expression) matcher.parameter(0))) {\n"); recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); recipe.append(" }\n"); } diff --git a/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java b/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java index 82fa3e98..42b56763 100644 --- a/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java +++ b/src/main/java/org/openrewrite/java/template/internal/ImportDetector.java @@ -57,9 +57,8 @@ public void scan(JCTree tree) { } } - // skip lhs of annotation assignments - if (tree instanceof JCTree.JCAssign) { - super.scan(((JCTree.JCAssign) tree).rhs); + if (tree instanceof JCTree.JCAnnotation) { + // completely skip annotations for now return; } diff --git a/src/test/resources/recipes/MatchingRecipes.java b/src/test/resources/recipes/MatchingRecipes.java index e7b48fc3..e17c2fd9 100644 --- a/src/test/resources/recipes/MatchingRecipes.java +++ b/src/test/resources/recipes/MatchingRecipes.java @@ -1,17 +1,18 @@ package foo; import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.search.*; import org.openrewrite.java.template.Primitive; import org.openrewrite.java.tree.*; import java.util.Arrays; import java.util.List; -import org.openrewrite.java.template.MethodInvocationMatcher; public final class MatchingRecipes extends Recipe { @@ -47,7 +48,7 @@ public String getDescription() { @Override public TreeVisitor getVisitor() { - return new JavaVisitor() { + JavaVisitor javaVisitor = new JavaVisitor() { final JavaTemplate before = JavaTemplate.compile(this, "before", (JavaTemplate.F1) (String s) -> s.isEmpty()).build(); final JavaTemplate after = JavaTemplate.compile(this, "after", (String s) -> s != null && s.length() == 0).build(); @@ -55,10 +56,9 @@ public TreeVisitor getVisitor() { public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { JavaTemplate.Matcher matcher; if ((matcher = before.matcher(getCursor())).find()) { - if (new MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) { + if (new org.openrewrite.java.template.MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) { return super.visitMethodInvocation(elem, ctx); } - maybeRemoveImport("org.openrewrite.java.template.MethodInvocationMatcher"); doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); @@ -67,7 +67,9 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { } }; + return javaVisitor; } } } + \ No newline at end of file From 804f924e34bea031fea4d7c6a22034de39d77b00 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Fri, 18 Aug 2023 21:51:49 +0200 Subject: [PATCH 3/6] Support annotation on all params --- .../template/RefasterTemplateProcessor.java | 129 +++++++++--------- src/test/resources/recipes/Matching.java | 6 + .../resources/recipes/MatchingRecipes.java | 14 +- .../recipes/ShouldAddImportsRecipes.java | 7 +- 4 files changed, 90 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java index a1314820..88f5ad86 100644 --- a/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/RefasterTemplateProcessor.java @@ -273,74 +273,79 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { } recipe.append(" JavaTemplate.Matcher matcher;\n"); - String predicate = befores.keySet().stream().map(b -> "(matcher = " + b + ".matcher(getCursor())).find()").collect(Collectors.joining(" || ")); - recipe.append(" if (" + predicate + ") {\n"); - for (JCTree.JCAnnotation jcAnnotation : befores.entrySet().iterator().next().getValue().getParameters().get(0).getModifiers().getAnnotations()) { - String annotationType = ((JCTree.JCIdent) jcAnnotation.annotationType).sym.getQualifiedName().toString(); - if (annotationType.equals("org.openrewrite.java.template.NotMatches")) { - String matcher = ((JCTree.JCAssign) jcAnnotation.getArguments().get(0)).getExpression().type.getTypeArguments().get(0).tsym.getQualifiedName().toString(); - recipe.append(" if (new " + matcher + "().matches((Expression) matcher.parameter(0))) {\n"); - recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); - recipe.append(" }\n"); - } else if (annotationType.equals("org.openrewrite.java.template.Matches")) { - String matcher = ((JCTree.JCAssign) jcAnnotation.getArguments().get(0)).getExpression().type.getTypeArguments().get(0).tsym.getQualifiedName().toString(); - recipe.append(" if (!new " + matcher + "().matches((Expression) matcher.parameter(0))) {\n"); - recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); - recipe.append(" }\n"); + for (Map.Entry entry : befores.entrySet()) { + recipe.append(" if (" + "(matcher = " + entry.getKey() + ".matcher(getCursor())).find()" + ") {\n"); + for (JCTree.JCVariableDecl param : entry.getValue().getParameters()) { + com.sun.tools.javac.util.List annotations = param.getModifiers().getAnnotations(); + for (int i = 0; i < annotations.size(); i++) { + JCTree.JCAnnotation jcAnnotation = annotations.get(i); + String annotationType = jcAnnotation.attribute.type.tsym.getQualifiedName().toString(); + if (annotationType.equals("org.openrewrite.java.template.NotMatches")) { + String matcher = ((Type.ClassType) jcAnnotation.attribute.getValue().values.get(0).snd.getValue()).tsym.getQualifiedName().toString(); + recipe.append(" if (new " + matcher + "().matches((Expression) matcher.parameter(" + i + "))) {\n"); + recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); + recipe.append(" }\n"); + } else if (annotationType.equals("org.openrewrite.java.template.Matches")) { + String matcher = ((Type.ClassType) jcAnnotation.attribute.getValue().values.get(0).snd.getValue()).tsym.getQualifiedName().toString(); + recipe.append(" if (!new " + matcher + "().matches((Expression) matcher.parameter(" + i + "))) {\n"); + recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); + recipe.append(" }\n"); + } + } } - } - Set beforeImports = imports.entrySet().stream() - .filter(e -> descriptor.beforeTemplates.contains(e.getKey())) - .map(Map.Entry::getValue) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - Set afterImports = imports.entrySet().stream() - .filter(e -> descriptor.afterTemplate == e.getKey()) - .map(Map.Entry::getValue) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - for (String import_ : imports.values().stream().flatMap(Set::stream).collect(Collectors.toSet())) { - if (import_.startsWith("java.lang.")) { - continue; + Set beforeImports = imports.entrySet().stream() + .filter(e -> entry.getValue().equals(e.getKey())) + .map(Map.Entry::getValue) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + Set afterImports = imports.entrySet().stream() + .filter(e -> descriptor.afterTemplate == e.getKey()) + .map(Map.Entry::getValue) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + for (String import_ : imports.values().stream().flatMap(Set::stream).collect(Collectors.toSet())) { + if (import_.startsWith("java.lang.")) { + continue; + } + if (beforeImports.contains(import_) && afterImports.contains(import_)) { + } else if (beforeImports.contains(import_)) { + recipe.append(" maybeRemoveImport(\"" + import_ + "\");\n"); + } else if (afterImports.contains(import_)) { + recipe.append(" maybeAddImport(\"" + import_ + "\");\n"); + } } - if (beforeImports.contains(import_) && afterImports.contains(import_)) { - } else if (beforeImports.contains(import_)) { - recipe.append(" maybeRemoveImport(\"" + import_ + "\");\n"); - } else if (afterImports.contains(import_)) { - recipe.append(" maybeAddImport(\"" + import_ + "\");\n"); + beforeImports = staticImports.entrySet().stream() + .filter(e -> entry.getValue().equals(e.getKey())) + .map(Map.Entry::getValue) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + afterImports = staticImports.entrySet().stream() + .filter(e -> descriptor.afterTemplate == e.getKey()) + .map(Map.Entry::getValue) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + for (String import_ : staticImports.values().stream().flatMap(Set::stream).collect(Collectors.toSet())) { + int dot = import_.lastIndexOf('.'); + if (import_.startsWith("java.lang.")) { + continue; + } + if (beforeImports.contains(import_) && afterImports.contains(import_)) { + } else if (beforeImports.contains(import_)) { + recipe.append(" maybeRemoveImport(\"" + import_ + "\");\n"); + } else if (afterImports.contains(import_)) { + recipe.append(" maybeAddImport(\"" + import_.substring(0, dot) + "\", \"" + import_.substring(dot + 1) + "\");\n"); + } } - } - beforeImports = staticImports.entrySet().stream() - .filter(e -> descriptor.beforeTemplates.contains(e.getKey())) - .map(Map.Entry::getValue) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - afterImports = staticImports.entrySet().stream() - .filter(e -> descriptor.afterTemplate == e.getKey()) - .map(Map.Entry::getValue) - .flatMap(Set::stream) - .collect(Collectors.toSet()); - for (String import_ : staticImports.values().stream().flatMap(Set::stream).collect(Collectors.toSet())) { - int dot = import_.lastIndexOf('.'); - if (import_.startsWith("java.lang.")) { - continue; + for (String doAfterVisit : DO_AFTER_VISIT) { + recipe.append(" doAfterVisit(" + doAfterVisit + ");\n"); } - if (beforeImports.contains(import_) && afterImports.contains(import_)) { - } else if (beforeImports.contains(import_)) { - recipe.append(" maybeRemoveImport(\"" + import_ + "\");\n"); - } else if (afterImports.contains(import_)) { - recipe.append(" maybeAddImport(\"" + import_.substring(0, dot) + "\", \"" + import_.substring(dot + 1) + "\");\n"); + if (parameters.isEmpty()) { + recipe.append(" return " + after + ".apply(getCursor(), elem.getCoordinates().replace());\n"); + } else { + recipe.append(" return " + after + ".apply(getCursor(), elem.getCoordinates().replace(), " + parameters + ");\n"); } + recipe.append(" }\n"); } - for (String doAfterVisit : DO_AFTER_VISIT) { - recipe.append(" doAfterVisit(" + doAfterVisit + ");\n"); - } - if (parameters.isEmpty()) { - recipe.append(" return " + after + ".apply(getCursor(), elem.getCoordinates().replace());\n"); - } else { - recipe.append(" return " + after + ".apply(getCursor(), elem.getCoordinates().replace(), " + parameters + ");\n"); - } - recipe.append(" }\n"); recipe.append(" return super.visit" + methodSuffix + "(elem, ctx);\n"); recipe.append(" }\n"); recipe.append("\n"); diff --git a/src/test/resources/recipes/Matching.java b/src/test/resources/recipes/Matching.java index 141a824a..973dd521 100644 --- a/src/test/resources/recipes/Matching.java +++ b/src/test/resources/recipes/Matching.java @@ -2,6 +2,7 @@ import com.google.errorprone.refaster.annotation.AfterTemplate; import com.google.errorprone.refaster.annotation.BeforeTemplate; +import org.openrewrite.java.template.Matches; import org.openrewrite.java.template.MethodInvocationMatcher; import org.openrewrite.java.template.NotMatches; @@ -13,6 +14,11 @@ boolean before(@NotMatches(MethodInvocationMatcher.class) String s) { return s.isEmpty(); } + @BeforeTemplate + boolean before2(@Matches(MethodInvocationMatcher.class) String s) { + return s.isEmpty(); + } + @AfterTemplate boolean after(String s) { return s != null && s.length() == 0; diff --git a/src/test/resources/recipes/MatchingRecipes.java b/src/test/resources/recipes/MatchingRecipes.java index e17c2fd9..c3b1254d 100644 --- a/src/test/resources/recipes/MatchingRecipes.java +++ b/src/test/resources/recipes/MatchingRecipes.java @@ -43,13 +43,14 @@ public String getDisplayName() { @Override public String getDescription() { - return "Recipe created for the following Refaster template:\n```java\npublic static class StringIsEmpty {\n \n @BeforeTemplate()\n boolean before(@NotMatches(value = MethodInvocationMatcher.class)\n String s) {\n return s.isEmpty();\n }\n \n @AfterTemplate()\n boolean after(String s) {\n return s != null && s.length() == 0;\n }\n}\n```\n."; + return "Recipe created for the following Refaster template:\n```java\npublic static class StringIsEmpty {\n \n @BeforeTemplate()\n boolean before(@NotMatches(value = MethodInvocationMatcher.class)\n String s) {\n return s.isEmpty();\n }\n \n @BeforeTemplate()\n boolean before2(@Matches(value = MethodInvocationMatcher.class)\n String s) {\n return s.isEmpty();\n }\n \n @AfterTemplate()\n boolean after(String s) {\n return s != null && s.length() == 0;\n }\n}\n```\n."; } @Override public TreeVisitor getVisitor() { JavaVisitor javaVisitor = new JavaVisitor() { final JavaTemplate before = JavaTemplate.compile(this, "before", (JavaTemplate.F1) (String s) -> s.isEmpty()).build(); + final JavaTemplate before2 = JavaTemplate.compile(this, "before2", (JavaTemplate.F1) (String s) -> s.isEmpty()).build(); final JavaTemplate after = JavaTemplate.compile(this, "after", (String s) -> s != null && s.length() == 0).build(); @Override @@ -63,6 +64,14 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); } + if ((matcher = before2.matcher(getCursor())).find()) { + if (!new org.openrewrite.java.template.MethodInvocationMatcher().matches((Expression) matcher.parameter(0))) { + return super.visitMethodInvocation(elem, ctx); + } + doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); + } return super.visitMethodInvocation(elem, ctx); } @@ -71,5 +80,4 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { } } -} - \ No newline at end of file +} \ No newline at end of file diff --git a/src/test/resources/recipes/ShouldAddImportsRecipes.java b/src/test/resources/recipes/ShouldAddImportsRecipes.java index 93f26b80..f79074dd 100644 --- a/src/test/resources/recipes/ShouldAddImportsRecipes.java +++ b/src/test/resources/recipes/ShouldAddImportsRecipes.java @@ -96,12 +96,17 @@ public TreeVisitor getVisitor() { @Override public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { JavaTemplate.Matcher matcher; - if ((matcher = equals.matcher(getCursor())).find() || (matcher = compareZero.matcher(getCursor())).find()) { + if ((matcher = equals.matcher(getCursor())).find()) { maybeRemoveImport("java.util.Objects"); doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); return isis.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)); } + if ((matcher = compareZero.matcher(getCursor())).find()) { + doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + return isis.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)); + } return super.visitMethodInvocation(elem, ctx); } From e821fd49d01776028c717e5cd263730d1b84cf69 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Tue, 22 Aug 2023 17:43:33 +0200 Subject: [PATCH 4/6] Fix failing test --- .../recipes/NestedPreconditionsRecipe.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/test/resources/recipes/NestedPreconditionsRecipe.java b/src/test/resources/recipes/NestedPreconditionsRecipe.java index 915973bf..b4b51345 100644 --- a/src/test/resources/recipes/NestedPreconditionsRecipe.java +++ b/src/test/resources/recipes/NestedPreconditionsRecipe.java @@ -1,4 +1,3 @@ - package foo; import org.openrewrite.ExecutionContext; @@ -38,22 +37,26 @@ public TreeVisitor getVisitor() { @Override public J visitExpression(Expression elem, ExecutionContext ctx) { JavaTemplate.Matcher matcher; - if ((matcher = hashMap.matcher(getCursor())).find() || (matcher = linkedHashMap.matcher(getCursor())).find()) { - maybeRemoveImport("java.util.LinkedHashMap"); + if ((matcher = hashMap.matcher(getCursor())).find()) { maybeRemoveImport("java.util.HashMap"); maybeAddImport("java.util.Hashtable"); doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); return hashtable.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)); } + if ((matcher = linkedHashMap.matcher(getCursor())).find()) { + maybeRemoveImport("java.util.LinkedHashMap"); + maybeAddImport("java.util.Hashtable"); + doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + return hashtable.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)); + } return super.visitExpression(elem, ctx); } }; return Preconditions.check( - Preconditions.or( - Preconditions.and(new UsesType<>("java.util.HashMap", true), new UsesType<>("java.util.Map", true)), - Preconditions.and(new UsesType<>("java.util.LinkedHashMap", true), new UsesType<>("java.util.Map", true))), + Preconditions.or(Preconditions.and(new UsesType<>("java.util.HashMap", true), new UsesType<>("java.util.Map", true)), Preconditions.and(new UsesType<>("java.util.LinkedHashMap", true), new UsesType<>("java.util.Map", true))), javaVisitor); } } From 7477cbe5d0940f00680696151a13f881e1049505 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Tue, 22 Aug 2023 17:46:35 +0200 Subject: [PATCH 5/6] Merge from main --- src/test/resources/recipes/MatchingRecipes.java | 4 +++- src/test/resources/recipes/NestedPreconditionsRecipe.java | 3 ++- src/test/resources/recipes/ShouldAddImportsRecipes.java | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/resources/recipes/MatchingRecipes.java b/src/test/resources/recipes/MatchingRecipes.java index c3b1254d..5ec16d92 100644 --- a/src/test/resources/recipes/MatchingRecipes.java +++ b/src/test/resources/recipes/MatchingRecipes.java @@ -18,7 +18,7 @@ public final class MatchingRecipes extends Recipe { @Override public String getDisplayName() { - return "Refaster recipes for `foo.Matching`"; + return "`Matching` Refaster recipes"; } @Override @@ -62,6 +62,7 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { } doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.SimplifyBooleanExpressionVisitor()); return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); } if ((matcher = before2.matcher(getCursor())).find()) { @@ -70,6 +71,7 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { } doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.SimplifyBooleanExpressionVisitor()); return after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(0)); } return super.visitMethodInvocation(elem, ctx); diff --git a/src/test/resources/recipes/NestedPreconditionsRecipe.java b/src/test/resources/recipes/NestedPreconditionsRecipe.java index e8f43d46..8f44e1bb 100644 --- a/src/test/resources/recipes/NestedPreconditionsRecipe.java +++ b/src/test/resources/recipes/NestedPreconditionsRecipe.java @@ -50,6 +50,7 @@ public J visitExpression(Expression elem, ExecutionContext ctx) { maybeAddImport("java.util.Hashtable"); doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.SimplifyBooleanExpressionVisitor()); return hashtable.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)); } return super.visitExpression(elem, ctx); @@ -60,4 +61,4 @@ public J visitExpression(Expression elem, ExecutionContext ctx) { Preconditions.or(Preconditions.and(new UsesType<>("java.util.HashMap", true), new UsesType<>("java.util.Map", true)), Preconditions.and(new UsesType<>("java.util.LinkedHashMap", true), new UsesType<>("java.util.Map", true))), javaVisitor); } -} +} \ No newline at end of file diff --git a/src/test/resources/recipes/ShouldAddImportsRecipes.java b/src/test/resources/recipes/ShouldAddImportsRecipes.java index f7aed670..8f21a36b 100644 --- a/src/test/resources/recipes/ShouldAddImportsRecipes.java +++ b/src/test/resources/recipes/ShouldAddImportsRecipes.java @@ -107,6 +107,7 @@ public J visitMethodInvocation(J.MethodInvocation elem, ExecutionContext ctx) { if ((matcher = compareZero.matcher(getCursor())).find()) { doAfterVisit(new org.openrewrite.java.ShortenFullyQualifiedTypeReferences().getVisitor()); doAfterVisit(new org.openrewrite.java.cleanup.UnnecessaryParenthesesVisitor()); + doAfterVisit(new org.openrewrite.java.cleanup.SimplifyBooleanExpressionVisitor()); return isis.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)); } return super.visitMethodInvocation(elem, ctx); From 6774ea9c13ef64c779d39c4ea49686559edb3086 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Tue, 22 Aug 2023 18:15:23 +0200 Subject: [PATCH 6/6] Try to remove `mavenLocal()` again --- build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1af155ff..b27c3acf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,7 +42,6 @@ dependencyCheck { } repositories { mavenCentral() - mavenLocal() } nexusPublishing {