diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c9839a9b7..7f7d33fc6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip -distributionSha256Sum=7a00d51fb93147819aab76024feece20b6b84e420694101f276be952e08bef03 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip +distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94 networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/org/openrewrite/staticanalysis/AbstractClassPublicConstructor.java b/src/main/java/org/openrewrite/staticanalysis/AbstractClassPublicConstructor.java new file mode 100644 index 000000000..c1a8e363a --- /dev/null +++ b/src/main/java/org/openrewrite/staticanalysis/AbstractClassPublicConstructor.java @@ -0,0 +1,66 @@ +/* + * Copyright 2025 the original author or authors. + *
+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://docs.moderne.io/licensing/moderne-source-available-license + *
+ * 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.
+ */
+package org.openrewrite.staticanalysis;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.internal.ListUtils;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+
+import java.util.Collections;
+import java.util.Set;
+
+import static org.openrewrite.java.tree.J.Modifier.Type.*;
+
+public class AbstractClassPublicConstructor extends Recipe {
+ @Override
+ public String getDisplayName() {
+ return "Constructors of an `abstract` class should not be declared `public`";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Constructors of `abstract` classes can only be called in constructors of their subclasses. " +
+ "Therefore the visibility of `public` constructors are reduced to `protected`.";
+ }
+
+ @Override
+ public Set
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.
+ */
+package org.openrewrite.staticanalysis;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.Issue;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+
+@SuppressWarnings("java:S2699")
+class AbstractClassPublicConstructorTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipe(new AbstractClassPublicConstructor());
+ }
+
+ @DocumentExample
+ @Test
+ void replacePublicByProtected() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ abstract class Test {
+ public Test() {
+ }
+ }
+ """,
+ """
+ abstract class Test {
+ protected Test() {
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void noReplaceOnNonAbstractClass() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class Test {
+ public Test() {
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void noReplaceOnPackageProtectedConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ abstract class Test {
+ Test() {
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/449")
+ @Test
+ void noReplaceOnNestedClasses() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ abstract class Test {
+ static class Nested {
+ public Nested() {
+ }
+ }
+ }
+ """
+ )
+ );
+ }
+}
diff --git a/src/test/java/org/openrewrite/staticanalysis/CatchClauseOnlyRethrowsTest.java b/src/test/java/org/openrewrite/staticanalysis/CatchClauseOnlyRethrowsTest.java
index 46990490f..81c812a95 100755
--- a/src/test/java/org/openrewrite/staticanalysis/CatchClauseOnlyRethrowsTest.java
+++ b/src/test/java/org/openrewrite/staticanalysis/CatchClauseOnlyRethrowsTest.java
@@ -45,7 +45,7 @@ void foo() throws IOException {
new FileReader("").read();
} catch (IOException e) {
throw new IOException("another message", e);
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception("another message");
}
}
@@ -70,9 +70,9 @@ void foo() throws IOException {
new FileReader("").read();
} catch (IOException e) {
throw e;
- } catch(Exception e) {
+ } catch (Exception e) {
System.out.println(e.getMessage());
- } catch(Throwable t) {
+ } catch (Throwable t) {
t.printStackTrace();
}
}
@@ -83,7 +83,60 @@ void foo() throws IOException {
}
@Test
- void catchShouldBePreservedBecauseLessSpecificCatchFollowsWithMultiCast() {
+ void catchShouldBePreservedBecauseLessSpecificCatchFollowsLater() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import java.io.FileReader;
+ import java.io.IOException;
+ import java.io.FileNotFoundException;
+
+ class A {
+ void foo() throws IOException {
+ try {
+ new FileReader("").read();
+ } catch (FileNotFoundException e) {
+ throw e;
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void multiCatchShouldBePreservedBecauseLessSpecificCatchFollows() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import java.io.FileReader;
+ import java.io.IOException;
+
+ class A {
+ void foo() throws IOException {
+ try {
+ new FileReader("").read();
+ } catch (IOException | RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void catchShouldBePreservedBecauseLessSpecificCatchFollowsWithMultiCatch() {
rewriteRun(
//language=java
java(
@@ -97,7 +150,32 @@ void foo() throws IOException {
new FileReader("").read();
} catch (IOException e) {
throw e;
- } catch(Exception | Throwable t) {
+ } catch (Exception | Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void mltiCatchShouldBePreservedBecauseLessSpecificCatchFollowsWithMultiCatch() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import java.io.FileReader;
+ import java.io.IOException;
+
+ class A {
+ void foo() throws IOException {
+ try {
+ new FileReader("").read();
+ } catch (IOException | RuntimeException e) {
+ throw e;
+ } catch (Exception | Throwable t) {
t.printStackTrace();
}
}
@@ -157,9 +235,9 @@ void foo() throws IOException {
new FileReader("").read();
} catch (FileNotFoundException e) {
throw e;
- } catch(IOException | ArrayIndexOutOfBoundsException e) {
+ } catch (IOException | ArrayIndexOutOfBoundsException e) {
throw e;
- } catch(Exception e) {
+ } catch (Exception e) {
throw e;
}
}
@@ -196,7 +274,7 @@ void foo() throws IOException {
new FileReader("").read();
} catch (FileNotFoundException e) {
throw e;
- } catch(IOException | ArrayIndexOutOfBoundsException e) {
+ } catch (IOException | ArrayIndexOutOfBoundsException e) {
throw new IOException("another message", e);
}
}
diff --git a/src/test/java/org/openrewrite/staticanalysis/NoValueOfOnStringTypeTest.java b/src/test/java/org/openrewrite/staticanalysis/NoValueOfOnStringTypeTest.java
index bf320e782..17bde044e 100644
--- a/src/test/java/org/openrewrite/staticanalysis/NoValueOfOnStringTypeTest.java
+++ b/src/test/java/org/openrewrite/staticanalysis/NoValueOfOnStringTypeTest.java
@@ -143,6 +143,23 @@ static void count(int i) {
);
}
+ @Test
+ @Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/456")
+ void valueOfOnNonStringPrimitiveWithBinaryArgument() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class Test {
+ static void method(int i) {
+ String s = String.valueOf(41 + 1);
+ }
+ }
+ """
+ )
+ );
+ }
+
@Test
@Issue("https://github.com/openrewrite/rewrite/issues/1200")
void valueOfIsMethodInvocationPartOfBinary() {
diff --git a/src/test/java/org/openrewrite/staticanalysis/RemoveExtraSemicolonsTest.java b/src/test/java/org/openrewrite/staticanalysis/RemoveExtraSemicolonsTest.java
index 1de29550e..06ccb8641 100644
--- a/src/test/java/org/openrewrite/staticanalysis/RemoveExtraSemicolonsTest.java
+++ b/src/test/java/org/openrewrite/staticanalysis/RemoveExtraSemicolonsTest.java
@@ -68,7 +68,7 @@ void enumSemicolonsWithOtherStatements() {
public enum FRUITS {
BANANA,
APPLE;
-
+
void hiFruit() {}
}
"""
@@ -215,6 +215,7 @@ int test() {
}
@Test
+ @DocumentExample
void repeatedSemicolon() {
rewriteRun(
//language=java
diff --git a/src/test/java/org/openrewrite/staticanalysis/UnnecessaryCatchTest.java b/src/test/java/org/openrewrite/staticanalysis/UnnecessaryCatchTest.java
index 5b785cc60..3395bd29d 100644
--- a/src/test/java/org/openrewrite/staticanalysis/UnnecessaryCatchTest.java
+++ b/src/test/java/org/openrewrite/staticanalysis/UnnecessaryCatchTest.java
@@ -27,7 +27,7 @@ class UnnecessaryCatchTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
- spec.recipe(new UnnecessaryCatch(false));
+ spec.recipe(new UnnecessaryCatch(false, false));
}
@DocumentExample
@@ -140,6 +140,33 @@ public void fred() throws IOException {
);
}
+ @Test
+ void doNotRemoveThrownExceptionFromConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import java.io.IOException;
+
+ public class AnExample {
+ public void method() {
+ try {
+ new Fred();
+ } catch (IOException e) {
+ System.out.println("an exception!");
+ }
+ }
+
+ public static class Fred {
+ public Fred() throws IOException {}
+ }
+
+ }
+ """
+ )
+ );
+ }
+
@Test
void doNotRemoveJavaLangException() {
rewriteRun(
@@ -159,4 +186,24 @@ void method() {
)
);
}
+
+ @Test
+ void doNotRemoveJavaLangThrowable() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class Scratch {
+ void method() {
+ try {
+ throw new RuntimeException();
+ } catch (Throwable e) {
+ System.out.println("an exception!");
+ }
+ }
+ }
+ """
+ )
+ );
+ }
}