1717
1818import org .jspecify .annotations .Nullable ;
1919import org .openrewrite .ExecutionContext ;
20+ import org .openrewrite .Preconditions ;
2021import org .openrewrite .Recipe ;
22+ import org .openrewrite .TreeVisitor ;
2123import org .openrewrite .java .JavaTemplate ;
2224import org .openrewrite .java .JavaVisitor ;
2325import org .openrewrite .java .MethodMatcher ;
24- import org .openrewrite .java .tree .*;
26+ import org .openrewrite .java .search .UsesMethod ;
27+ import org .openrewrite .java .tree .Expression ;
28+ import org .openrewrite .java .tree .J ;
2529import org .openrewrite .java .tree .J .FieldAccess ;
2630import org .openrewrite .java .tree .J .Identifier ;
2731import org .openrewrite .java .tree .J .MethodInvocation ;
32+ import org .openrewrite .java .tree .JavaCoordinates ;
33+ import org .openrewrite .java .tree .JavaType ;
2834
2935import java .util .Collections ;
3036import java .util .Set ;
3137
3238public class ReplaceClassIsInstanceWithInstanceof extends Recipe {
3339
40+ private static final MethodMatcher ISINSTANCE_MATCHER = new MethodMatcher ("java.lang.Class isInstance(..)" );
41+
3442 @ Override
3543 public String getDisplayName () {
3644 return "Replace `A.class.isInstance(a)` with `a instanceof A`" ;
@@ -47,25 +55,22 @@ public Set<String> getTags() {
4755 }
4856
4957 @ Override
50- public JavaVisitor < ExecutionContext > getVisitor () {
58+ public TreeVisitor <?, ExecutionContext > getVisitor () {
5159 // use JavaVisitor instead of JavaIsoVisitor because we changed the type of LST
52- return new JavaVisitor <ExecutionContext >() {
53-
54- private final MethodMatcher matcher = new MethodMatcher ("java.lang.Class isInstance(java.lang.Object)" );
60+ return Preconditions .check (new UsesMethod <>(ISINSTANCE_MATCHER ), new JavaVisitor <ExecutionContext >() {
5561
5662 @ Override
5763 public J visitMethodInvocation (MethodInvocation method , ExecutionContext ctx ) {
5864 // make sure we find the right method and the left part is something like "SomeClass.class"
59- if (matcher .matches (method ) && isObjectClass (method .getSelect ())) {
65+ if (ISINSTANCE_MATCHER .matches (method ) && isObjectClass (method .getSelect ())) {
6066 // for code like "A.class.isInstance(a)", select is "String.class", name is "isInstance", argument is "a"
6167 Expression objectExpression = method .getArguments ().get (0 );
6268 FieldAccess fieldAccessPart = (FieldAccess ) method .getSelect ();
63- String className = fieldAccessPart .getTarget ().toString ();
6469 // upcast to type J, so J.MethodInvocation can be replaced by J.InstanceOf
6570 JavaCoordinates coordinates = method .getCoordinates ().replace ();
66- J .InstanceOf instanceOf = JavaTemplate .builder ("#{any()} instanceof #{} " )
71+ J .InstanceOf instanceOf = JavaTemplate .builder ("#{any()} instanceof Object " )
6772 .build ()
68- .apply (getCursor (), coordinates , new Object []{ objectExpression , className } );
73+ .apply (getCursor (), coordinates , objectExpression );
6974 instanceOf = instanceOf .withClazz (fieldAccessPart .getTarget ().withPrefix (instanceOf .getClazz ().getPrefix ()));
7075 return maybeAutoFormat (method , instanceOf , ctx );
7176 }
@@ -75,13 +80,13 @@ public J visitMethodInvocation(MethodInvocation method, ExecutionContext ctx) {
7580 private boolean isObjectClass (@ Nullable Expression expression ) {
7681 if (expression instanceof J .FieldAccess ) {
7782 J .FieldAccess fieldAccess = (J .FieldAccess ) expression ;
78- if (fieldAccess .getTarget () instanceof Identifier ) {
83+ if (fieldAccess .getName (). getSimpleName (). equals ( "class" ) && fieldAccess . getTarget () instanceof Identifier ) {
7984 Identifier identifier = (Identifier ) fieldAccess .getTarget ();
8085 return identifier .getType () instanceof JavaType .Class ;
8186 }
8287 }
8388 return false ;
8489 }
85- };
90+ }) ;
8691 }
8792}
0 commit comments