openrewrite / rewrite-templating

Automated templating using code snippets.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support `return Refaster.anyOf(...)`

timtebeek opened this issue · comments

What problem are you trying to solve?

Right now we skip all refaster rules using any form of Refaster.anyOf(...), whereas we could potentially cover return Refaster.anyOf(...) with less effort as compared to supporting Refaster.anyOf(...) anywhere in template for matches.
This will allow us to cover additional rules defined in PicnicSupermarket/error-prone-support, as discovered in #5 (comment).

Describe the solution you'd like

We already support multiple @BeforeTemplate annotated methods. We should expand support for multiple before statements to cover return Refaster.anyOf as seen here.

@BeforeTemplate
boolean before(Map<K, V> map) {
  return Refaster.anyOf(map.keySet(), map.values(), map.entrySet()).isEmpty();
}

Refaster.anyOf(...) used anywhere else but in the return, repeatedly, or with preceding statements is left out of scope for now.

Have you considered any alternatives or workarounds?

Not yet.

Additional context

Had a brief look at adding this one over the weekend; the easiest case to tackle is likely something like this:

public class RefasterAnyOf {
    @BeforeTemplate
    boolean before(String s) {
        return Refaster.anyOf(s.length() < 1, s.length() == 0);
    }

    @AfterTemplate
    boolean after(String s) {
        return s.isEmpty();
    }
}

And then ideally turn that into something similar to the multiple before statements we already know:

JavaTemplate before = Semantics.expression(this, "before", (String s) -> s.length() < 1).build();
JavaTemplate before2 = Semantics.expression(this, "before2", (String s) -> s.length() == 0).build();
JavaTemplate after = Semantics.expression(this, "after", (String s) -> s.isEmpty()).build();

Implementation wise there's the slight challenge of the List<JCTree.JCMethodDecl> beforeTemplates being passed around and used four different times for imports, template naming, lambda bodies and preconditions. The challenge is then where to detect Refaster.anyOf and how to adapt the code to use it's arguments.

The arguments to Refaster.anyOf() should also be considered as separate when detecting the used types and methods to build the UsedType and UsedMethod preconditions.

Fixed in #76

It also works when the anyOf() is not directly the return expression. What doesn't work ia if a template contains multiple such calls.