diff --git a/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java b/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java index a3afe0b1..84b8dd59 100644 --- a/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java @@ -25,6 +25,7 @@ import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Name; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.template.internal.FQNPretty; import org.openrewrite.java.template.internal.ImportDetector; @@ -181,7 +182,9 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { String after = descriptor.afterTemplate.getName().toString(); StringBuilder recipe = new StringBuilder(); - String refasterRuleClassName = classDecl.sym.fullname.toString().substring(classDecl.sym.packge().fullname.length() + 1); + Symbol.PackageSymbol pkg = classDecl.sym.packge(); + String typeName = classDecl.sym.fullname.toString(); + String refasterRuleClassName = pkg.isUnnamed() ? typeName : typeName.substring(pkg.fullname.length() + 1); recipe.append("/**\n * OpenRewrite recipe created for Refaster template {@code ").append(refasterRuleClassName).append("}.\n */\n"); String recipeName = templateFqn.substring(templateFqn.lastIndexOf('.') + 1); recipe.append("@SuppressWarnings(\"all\")\n"); @@ -306,12 +309,15 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { if (classDecl.sym != null && classDecl.sym.getNestingKind() == NestingKind.TOP_LEVEL && !recipes.isEmpty()) { boolean outerClassRequired = descriptor == null; try { + Symbol.PackageSymbol pkg = classDecl.sym.packge(); String inputOuterFQN = outerClassRequired ? classDecl.sym.fullname.toString() : descriptor.classDecl.sym.fullname.toString(); String className = inputOuterFQN + (outerClassRequired ? "Recipes" : "Recipe"); JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(className); try (Writer out = new BufferedWriter(builderFile.openWriter())) { - out.write("package " + classDecl.sym.packge().toString() + ";\n"); - out.write("\n"); + if (!pkg.isUnnamed()) { + out.write("package " + pkg.fullname + ";\n"); + out.write("\n"); + } out.write("import org.openrewrite.ExecutionContext;\n"); out.write("import org.openrewrite.Preconditions;\n"); out.write("import org.openrewrite.Recipe;\n"); diff --git a/src/main/java/org/openrewrite/java/template/processor/TemplateProcessor.java b/src/main/java/org/openrewrite/java/template/processor/TemplateProcessor.java index 74e21389..10dea5f1 100644 --- a/src/main/java/org/openrewrite/java/template/processor/TemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/processor/TemplateProcessor.java @@ -140,9 +140,13 @@ public void visitApply(JCTree.JCMethodInvocation tree) { String templateCode = TemplateCode.process(resolved.get(template.getBody()), parameters, false); + Symbol.PackageSymbol pkg = classDecl.sym.packge(); JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(templateFqn); try (Writer out = new BufferedWriter(builderFile.openWriter())) { - out.write("package " + classDecl.sym.packge().toString() + ";\n"); + if (!pkg.isUnnamed()) { + out.write("package " + pkg.fullname + ";\n"); + out.write("\n"); + } out.write("import org.openrewrite.java.*;\n"); out.write("\n"); diff --git a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java index 1916d3e2..36c1a358 100644 --- a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java +++ b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java @@ -19,6 +19,7 @@ import com.google.errorprone.refaster.annotation.BeforeTemplate; import com.google.testing.compile.Compilation; import com.google.testing.compile.JavaFileObjects; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.openrewrite.java.template.processor.RefasterTemplateProcessor; @@ -51,6 +52,16 @@ void generateRecipe(String recipeName) { .hasSourceEquivalentTo(JavaFileObjects.forResource("refaster/" + recipeName + "Recipe.java")); } + @Test + void generateRecipeInDefaultPackage() { + Compilation compilation = compile("refaster/UnnamedPackage.java"); + assertThat(compilation).succeeded(); + assertThat(compilation).hadNoteCount(0); + assertThat(compilation) + .generatedSourceFile("UnnamedPackageRecipe") + .hasSourceEquivalentTo(JavaFileObjects.forResource("refaster/UnnamedPackageRecipe.java")); + } + @ParameterizedTest @ValueSource(strings = { "OrElseGetGet", diff --git a/src/test/java/org/openrewrite/java/template/TemplateProcessorTest.java b/src/test/java/org/openrewrite/java/template/TemplateProcessorTest.java index 928c4cb2..39f9a580 100644 --- a/src/test/java/org/openrewrite/java/template/TemplateProcessorTest.java +++ b/src/test/java/org/openrewrite/java/template/TemplateProcessorTest.java @@ -74,4 +74,13 @@ void throwNew() { .generatedSourceFile("template/ThrowNewRecipe$1_template") .hasSourceEquivalentTo(JavaFileObjects.forResource("template/ThrowNewRecipe$1_template.java")); } + + @Test + void unnamedPackage() { + Compilation compilation = compile("template/UnnamedPackage.java", new TemplateProcessor()); + assertThat(compilation).succeeded(); + assertThat(compilation) + .generatedSourceFile("UnnamedPackage$1_message") + .hasSourceEquivalentTo(JavaFileObjects.forResource("template/UnnamedPackage$1_message.java")); + } } diff --git a/src/test/resources/refaster/UnnamedPackage.java b/src/test/resources/refaster/UnnamedPackage.java new file mode 100644 index 00000000..91537abb --- /dev/null +++ b/src/test/resources/refaster/UnnamedPackage.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 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. + */ +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; + +public class UnnamedPackage { + @BeforeTemplate + String before() { + return "This class is located in the default package"; + } + + @AfterTemplate + String after() { + return "And that doesn't cause any problems"; + } +} diff --git a/src/test/resources/refaster/UnnamedPackageRecipe.java b/src/test/resources/refaster/UnnamedPackageRecipe.java new file mode 100644 index 00000000..63ccaf3b --- /dev/null +++ b/src/test/resources/refaster/UnnamedPackageRecipe.java @@ -0,0 +1,75 @@ +/* + * Copyright 2024 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. + */ +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.lang.NonNullApi; +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.template.Semantics; +import org.openrewrite.java.template.function.*; +import org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor; +import org.openrewrite.java.tree.*; + +import java.util.*; + +import static org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor.EmbeddingOption.*; + + +/** + * OpenRewrite recipe created for Refaster template {@code UnnamedPackage}. + */ +@SuppressWarnings("all") +@NonNullApi +public class UnnamedPackageRecipe extends Recipe { + + /** + * Instantiates a new instance. + */ + public UnnamedPackageRecipe() {} + + @Override + public String getDisplayName() { + return "Refaster template `UnnamedPackage`"; + } + + @Override + public String getDescription() { + return "Recipe created for the following Refaster template:\n```java\npublic class UnnamedPackage {\n \n @BeforeTemplate()\n String before() {\n return \"This class is located in the default package\";\n }\n \n @AfterTemplate()\n String after() {\n return \"And that doesn\\'t cause any problems\";\n }\n}\n```\n."; + } + + @Override + public TreeVisitor getVisitor() { + JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() { + final JavaTemplate before = Semantics.expression(this, "before", () -> "This class is located in the default package").build(); + final JavaTemplate after = Semantics.expression(this, "after", () -> "And that doesn\'t cause any problems").build(); + + @Override + public J visitExpression(Expression elem, ExecutionContext ctx) { + JavaTemplate.Matcher matcher; + if ((matcher = before.matcher(getCursor())).find()) { + return embed(after.apply(getCursor(), elem.getCoordinates().replace()), getCursor(), ctx); + } + return super.visitExpression(elem, ctx); + } + + }; + return javaVisitor; + } +} diff --git a/src/test/resources/template/UnnamedPackage$1_message.java b/src/test/resources/template/UnnamedPackage$1_message.java new file mode 100644 index 00000000..b6bf1331 --- /dev/null +++ b/src/test/resources/template/UnnamedPackage$1_message.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 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. + */ +import org.openrewrite.java.*; + +/** + * OpenRewrite `message` template created for {@code UnnamedPackage$1}. + */ +@SuppressWarnings("all") +public class UnnamedPackage$1_message { + /** + * Instantiates a new instance. + */ + public UnnamedPackage$1_message() {} + + /** + * Get the {@code JavaTemplate.Builder} to match or replace. + * @return the JavaTemplate builder. + */ + public static JavaTemplate.Builder getTemplate() { + return JavaTemplate + .builder("\"This class is located in the default package\""); + } +} diff --git a/src/test/resources/template/UnnamedPackage.java b/src/test/resources/template/UnnamedPackage.java new file mode 100644 index 00000000..a50bc996 --- /dev/null +++ b/src/test/resources/template/UnnamedPackage.java @@ -0,0 +1,25 @@ +/* + * Copyright 2024 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. + */ +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.template.Semantics; + +public class UnnamedPackage { + JavaIsoVisitor visitor = new JavaIsoVisitor() { + JavaTemplate.Builder message = Semantics.expression(this, "message", () -> "This class is located in the default package"); + }; +}