Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support sources located in an unnamed package #64

Merged
merged 1 commit into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deduplicating classDecl.sym.packge() and classDecl.sym.fullname.toString() at the top of this method would yield an NPE, unless more things are refactored. But that would likely change the indentation of most of the code in this method, which would make the PR way harder to review. Seems better to refactor that separately (if at all).

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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
}
}
29 changes: 29 additions & 0 deletions src/test/resources/refaster/UnnamedPackage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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";
}
}
75 changes: 75 additions & 0 deletions src/test/resources/refaster/UnnamedPackageRecipe.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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<?, ExecutionContext> getVisitor() {
JavaVisitor<ExecutionContext> 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;
}
}
36 changes: 36 additions & 0 deletions src/test/resources/template/UnnamedPackage$1_message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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\"");
}
}
25 changes: 25 additions & 0 deletions src/test/resources/template/UnnamedPackage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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<ExecutionContext>() {
JavaTemplate.Builder message = Semantics.expression(this, "message", () -> "This class is located in the default package");
};
}