diff --git a/src/main/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuper.java b/src/main/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuper.java index 29bc46da4..d900e03a3 100644 --- a/src/main/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuper.java +++ b/src/main/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuper.java @@ -23,14 +23,15 @@ import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.java.AnnotationMatcher; +import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaVisitor; -import org.openrewrite.java.service.AnnotationService; import org.openrewrite.java.tree.*; import org.openrewrite.staticanalysis.kotlin.KotlinFileChecker; import java.time.Duration; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import static java.util.Collections.singleton; @@ -85,11 +86,8 @@ public TreeVisitor getVisitor() { return md; } - // Skip if method has annotations other than @Override - for (J.Annotation annotation : service(AnnotationService.class).getAllAnnotations(getCursor())) { - if (!OVERRIDE.matches(annotation)) { - return md; - } + if (hasSemanticAnnotation(md)) { + return md; } // Skip if method has Javadoc comments @@ -110,6 +108,11 @@ public TreeVisitor getVisitor() { return md; } + if (md.hasModifier(J.Modifier.Type.Strictfp) && + (superCall.getMethodType() == null || !superCall.getMethodType().hasFlags(Flag.Strictfp))) { + return md; + } + // Skip if method widens visibility compared to the overridden method if (widensVisibility(methodType)) { return md; @@ -132,6 +135,23 @@ public TreeVisitor getVisitor() { return null; } + private boolean hasSemanticAnnotation(J.MethodDeclaration method) { + return new JavaIsoVisitor() { + @Override + public J.Annotation visitAnnotation(J.Annotation annotation, AtomicBoolean found) { + if (!OVERRIDE.matches(annotation)) { + found.set(true); + } + return annotation; + } + + @Override + public J.Block visitBlock(J.Block block, AtomicBoolean found) { + return block; + } + }.reduce(method, new AtomicBoolean()).get(); + } + private boolean argumentsMatchParameters(List parameters, List arguments) { int argIndex = 0; int paramCount = 0; diff --git a/src/test/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuperTest.java b/src/test/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuperTest.java index 5f10fe5aa..b42902b2b 100644 --- a/src/test/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuperTest.java +++ b/src/test/java/org/openrewrite/staticanalysis/RemoveMethodsOnlyCallSuperTest.java @@ -381,6 +381,99 @@ void save() { ); } + @Test + void doNotChangeMethodsWithSignatureAnnotations() { + rewriteRun( + //language=java + java( + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + + @Target({ElementType.PARAMETER, ElementType.TYPE_USE}) + @interface Nullable {} + + class Parent { + void foo(String s) { + } + + String[] bar() { + return new String[0]; + } + } + + class Child extends Parent { + @Override + void foo(@Nullable String s) { + super.foo(s); + } + + @Override + String @Nullable [] bar() { + return super.bar(); + } + } + """ + ) + ); + } + + @Test + void doNotChangeStrictfpMethod() { + rewriteRun( + //language=java + java( + """ + class Parent { + void foo() { + } + } + """ + ), + //language=java + java( + """ + class Child extends Parent { + @Override + strictfp void foo() { + super.foo(); + } + } + """ + ) + ); + } + + @Test + void removeStrictfpMethodWhenSuperIsStrictfpToo() { + rewriteRun( + //language=java + java( + """ + class Parent { + strictfp void foo() { + } + } + """ + ), + //language=java + java( + """ + class Child extends Parent { + @Override + strictfp void foo() { + super.foo(); + } + } + """, + """ + class Child extends Parent { + } + """ + ) + ); + } + @Test void doNotChangeMethodThatWidensVisibility() { rewriteRun(