Skip to content

Commit

Permalink
Support Refaster#anyOf() (#76)
Browse files Browse the repository at this point in the history
* Support `Refaster#anyOf()`

For `@BeforeTemplate` annotated methods which contain one `Refaster#anyOf()` call we can support that by generating a corresponding number of `JavaTemplate`s.

* Remove `TemplateDescriptor#resolvedParameters`

Instead, updating the method in place.

* Add `TemplateDescriptor#resolveMethod()` method

* Rename `TemplateDescriptor` to `RuleDescriptor`

Also add new `TemplateDescriptor` to represent actual template method.

* Mork work on `Refaster.anyOf()` support

* Some more refactoring

* Implement predicates for `anyOf()`

* Adjust import detection

* Correct template code generation

* Change test to also use an unqualified name

* Don't add any imports

Now that we skip the intermediate step with lambdas, there is no need to generate imports for any types from the template code.

* Properly support array type parameters

* Fix failing test
  • Loading branch information
knutwannheden authored Mar 7, 2024
1 parent ab2dee2 commit 7b766b8
Show file tree
Hide file tree
Showing 14 changed files with 704 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

public class ImportDetector {
/**
Expand All @@ -38,7 +39,11 @@ public class ImportDetector {
* @return The list of imports to add.
*/
public static List<Symbol> imports(JCTree.JCMethodDecl methodDecl) {
ImportScanner importScanner = new ImportScanner();
return imports(methodDecl, t -> true);
}

public static List<Symbol> imports(JCTree.JCMethodDecl methodDecl, Predicate<JCTree> scopePredicate) {
ImportScanner importScanner = new ImportScanner(scopePredicate);
importScanner.scan(methodDecl.getBody());
importScanner.scan(methodDecl.getReturnType());
for (JCTree.JCVariableDecl param : methodDecl.getParameters()) {
Expand All @@ -57,16 +62,25 @@ public static List<Symbol> imports(JCTree.JCMethodDecl methodDecl) {
* @return The list of imports to add.
*/
public static List<Symbol> imports(JCTree tree) {
ImportScanner importScanner = new ImportScanner();
ImportScanner importScanner = new ImportScanner(t -> true);
importScanner.scan(tree);
return new ArrayList<>(importScanner.imports);
}

private static class ImportScanner extends TreeScanner {
final Set<Symbol> imports = new LinkedHashSet<>();
private final Predicate<JCTree> scopePredicate;

public ImportScanner(Predicate<JCTree> scopePredicate) {
this.scopePredicate = scopePredicate;
}

@Override
public void scan(JCTree tree) {
if (!scopePredicate.test(tree)) {
return;
}

JCTree maybeFieldAccess = tree;
if (maybeFieldAccess instanceof JCFieldAccess &&
((JCFieldAccess) maybeFieldAccess).sym instanceof Symbol.ClassSymbol &&
Expand Down Expand Up @@ -113,6 +127,11 @@ public void scan(JCTree tree) {
&& ((JCIdent) ((JCFieldAccess) tree).selected).sym instanceof Symbol.ClassSymbol
&& !(((JCIdent) ((JCFieldAccess) tree).selected).sym.type instanceof Type.ErrorType)) {
imports.add(((JCIdent) ((JCFieldAccess) tree).selected).sym);
} else if (tree instanceof JCTree.JCFieldAccess &&
((JCTree.JCFieldAccess) tree).sym instanceof Symbol.ClassSymbol) {
if (tree.toString().equals(((JCTree.JCFieldAccess) tree).sym.toString())) {
imports.add(((JCTree.JCFieldAccess) tree).sym);
}
}

super.scan(tree);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.openrewrite.java.template.internal;

import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.Pretty;
Expand Down Expand Up @@ -94,12 +95,19 @@ public void visitIdent(JCIdent jcIdent) {
if (param.isPresent()) {
print("#{" + sym.name);
if (seenParameters.add(param.get())) {
String type = param.get().sym.type.toString();
if (param.get().getModifiers().getAnnotations().stream()
.anyMatch(a -> a.attribute.type.tsym.getQualifiedName().toString().equals(PRIMITIVE_ANNOTATION))) {
type = getUnboxedPrimitive(type);
Type type = param.get().sym.type;
String typeString;
if (type instanceof Type.ArrayType) {
print(":anyArray(" + ((Type.ArrayType) type).elemtype.toString() + ")");
} else {
if (param.get().getModifiers().getAnnotations().stream()
.anyMatch(a -> a.attribute.type.tsym.getQualifiedName().toString().equals(PRIMITIVE_ANNOTATION))) {
typeString = getUnboxedPrimitive(type.toString());
} else {
typeString = type.toString();
}
print(":any(" + typeString + ")");
}
print(":any(" + type + ")");
}
print("}");
} else if (sym != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,21 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

public class UsedMethodDetector {

public static List<Symbol.MethodSymbol> usedMethods(JCTree input) {
return usedMethods(input, t -> true);
}

public static List<Symbol.MethodSymbol> usedMethods(JCTree input, Predicate<JCTree> scopePredicate) {
Set<Symbol.MethodSymbol> imports = new LinkedHashSet<>();

new TreeScanner() {
@Override
public void scan(JCTree tree) {
if (tree instanceof JCTree.JCAnnotation) {
if (tree instanceof JCTree.JCAnnotation || !scopePredicate.test(tree)) {
// completely skip annotations for now
return;
}
Expand Down
Loading

0 comments on commit 7b766b8

Please sign in to comment.