diff --git a/CHANGELOG.md b/CHANGELOG.md
index e657561c..ec4a2471 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
+- [#106](https://github.com/green-code-initiative/creedengo-java/pull/106) Add new Java rule GCI96 - Avoid Catching Runtime exceptions
### Changed
diff --git a/src/it/java/org/greencodeinitiative/creedengo/java/integration/tests/GCIRulesIT.java b/src/it/java/org/greencodeinitiative/creedengo/java/integration/tests/GCIRulesIT.java
index eff99826..1cd3d247 100644
--- a/src/it/java/org/greencodeinitiative/creedengo/java/integration/tests/GCIRulesIT.java
+++ b/src/it/java/org/greencodeinitiative/creedengo/java/integration/tests/GCIRulesIT.java
@@ -548,4 +548,47 @@ void testGCI94() {
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_1MIN);
}
+ @Test
+ void testGCI96_nominalRuntimeException() {
+ String filePath = "src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java";
+ String ruleId = "creedengo-java:GCI96";
+ String ruleMsg = "Avoid catching Runtime exceptions : RuntimeException";
+ int[] startLines = new int[]{36};
+ int[] endLines = new int[]{37};
+
+ checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
+ }
+
+ @Test
+ void testGCI96_IndexOutOfBoundsException() {
+ String filePath = "src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java";
+ String ruleId = "creedengo-java:GCI96";
+ String ruleMsg = "Avoid catching Runtime exceptions : IndexOutOfBoundsException";
+ int[] startLines = new int[]{44};
+ int[] endLines = new int[]{45};
+
+ checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
+ }
+
+ @Test
+ void testGCI96_NullPointerException() {
+ String filePath = "src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java";
+ String ruleId = "creedengo-java:GCI96";
+ String ruleMsg = "Avoid catching Runtime exceptions : NullPointerException";
+ int[] startLines = new int[]{52};
+ int[] endLines = new int[]{53};
+
+ checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
+ }
+
+ @Test
+ void testGCI96_ArithmeticException() {
+ String filePath = "src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java";
+ String ruleId = "creedengo-java:GCI96";
+ String ruleMsg = "Avoid catching Runtime exceptions : ArithmeticException";
+ int[] startLines = new int[]{59};
+ int[] endLines = new int[]{60};
+
+ checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
+ }
}
diff --git a/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidRuntimeExceptions.java b/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidRuntimeExceptions.java
new file mode 100644
index 00000000..647e6075
--- /dev/null
+++ b/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidRuntimeExceptions.java
@@ -0,0 +1,91 @@
+/*
+ * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs
+ * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.java.checks;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.RuntimeException;
+import java.lang.ArithmeticException;
+import java.lang.IndexOutOfBoundsException;
+import java.lang.NullPointerException;
+import java.lang.IllegalArgumentException;
+import java.lang.NumberFormatException;
+import java.lang.Integer;
+
+public class AvoidRuntimeExceptions {
+ public void nominalRuntimeException() {
+ try {
+ // some code that may throw an exception
+ } catch (RuntimeException e) { // Noncompliant {{Avoid catching Runtime exceptions : RuntimeException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant() {
+ int[] array = new int[10];
+ try {
+ array[10] = 0;
+ } catch (IndexOutOfBoundsException e) { // Noncompliant {{Avoid catching Runtime exceptions : IndexOutOfBoundsException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant_2(){
+ Object obj = null;
+ try {
+ obj.toString();
+ } catch (NullPointerException e) { // Noncompliant {{Avoid catching Runtime exceptions : NullPointerException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant_3(){
+ try {
+ int result = 1 / 0;
+ } catch (ArithmeticException e) { // Noncompliant {{Avoid catching Runtime exceptions : ArithmeticException}}
+ }
+ }
+
+ //these exceptions are ok because they aren't runtime exceptions
+
+ public void compliantNonRuntimeException() {
+ try {
+ File file = new File("nonexistent.txt");
+ FileReader fr = new FileReader(file);
+ fr.read();
+ } catch (FileNotFoundException e) {
+ } catch (IOException e) {
+ }
+ }
+
+ // these exceptions are ok because they are IllegalArgumentExceptions, and can hardly be avoided
+
+ public void compliantIllegalArgumentException() {
+ try {
+ // some code that may throw an exception
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void compliantIllegalArgumentExceptionDependant() {
+ try {
+ Integer.parseInt("abc");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+}
diff --git a/src/main/java/org/greencodeinitiative/creedengo/java/JavaCheckRegistrar.java b/src/main/java/org/greencodeinitiative/creedengo/java/JavaCheckRegistrar.java
index 791f0cef..e0566553 100644
--- a/src/main/java/org/greencodeinitiative/creedengo/java/JavaCheckRegistrar.java
+++ b/src/main/java/org/greencodeinitiative/creedengo/java/JavaCheckRegistrar.java
@@ -50,7 +50,8 @@ public class JavaCheckRegistrar implements CheckRegistrar {
FreeResourcesOfAutoCloseableInterface.class,
AvoidMultipleIfElseStatement.class,
UseOptionalOrElseGetVsOrElse.class,
- MakeNonReassignedVariablesConstants.class
+ MakeNonReassignedVariablesConstants.class,
+ AvoidCatchingRuntimeExceptions.class
);
/**
diff --git a/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java b/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java
new file mode 100644
index 00000000..e7f82b7c
--- /dev/null
+++ b/src/main/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptions.java
@@ -0,0 +1,51 @@
+/*
+ * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs
+ * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.java.checks;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.sonar.check.Rule;
+import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
+import org.sonar.plugins.java.api.tree.CatchTree;
+import org.sonar.plugins.java.api.tree.Tree;
+import org.sonar.plugins.java.api.tree.Tree.Kind;
+
+@Rule(key = "GCI96")
+public class AvoidCatchingRuntimeExceptions extends IssuableSubscriptionVisitor {
+
+ protected static final String MESSAGERULE = "Avoid catching Runtime exceptions";
+ protected static final String RUNTIME_EXCEPTION = "java.lang.RuntimeException";
+ protected static final String ILLEGAL_ARGUMENT_EXCEPTION = "java.lang.IllegalArgumentException";
+
+ @Override
+ public List nodesToVisit() {
+ return Collections.singletonList(Kind.CATCH);
+ }
+
+ @Override
+ public void visitNode(Tree tree) {
+ CatchTree catchTree = (CatchTree) tree;
+ if(catchTree.parameter().type().symbolType().isSubtypeOf(RUNTIME_EXCEPTION) &&
+ !catchTree.parameter().type().symbolType().isSubtypeOf(ILLEGAL_ARGUMENT_EXCEPTION)) {
+ String caughtExceptionType = catchTree.parameter().type().symbolType().name();
+ String message = MESSAGERULE + " : " + caughtExceptionType;
+ reportIssue(tree, message);
+ }
+ }
+}
diff --git a/src/main/resources/org/greencodeinitiative/creedengo/java/creedengo_way_profile.json b/src/main/resources/org/greencodeinitiative/creedengo/java/creedengo_way_profile.json
index 059bf0f5..3ed057d5 100644
--- a/src/main/resources/org/greencodeinitiative/creedengo/java/creedengo_way_profile.json
+++ b/src/main/resources/org/greencodeinitiative/creedengo/java/creedengo_way_profile.json
@@ -18,6 +18,7 @@
"GCI78",
"GCI79",
"GCI82",
- "GCI94"
+ "GCI94",
+ "GCI96"
]
}
diff --git a/src/test/files/AvoidCatchingRuntimeExceptions.java b/src/test/files/AvoidCatchingRuntimeExceptions.java
new file mode 100644
index 00000000..82c0f4e0
--- /dev/null
+++ b/src/test/files/AvoidCatchingRuntimeExceptions.java
@@ -0,0 +1,91 @@
+/*
+ * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs
+ * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.java.checks;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.runtime.RuntimeException;
+import java.lang.ArithmeticException;
+import java.lang.IndexOutOfBoundsException;
+import java.lang.NullPointerException;
+import java.lang.IllegalArgumentException;
+import java.lang.NumberFormatException;
+import java.lang.Integer;
+
+public class AvoidCatchingRuntimeExceptions {
+ public void nominalRuntimeException() {
+ try {
+ // some code that may throw an exception
+ } catch (RuntimeException e) { // Noncompliant {{Avoid catching Runtime exceptions : RuntimeException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant() {
+ int[] array = new int[10];
+ try {
+ array[10] = 0;
+ } catch (IndexOutOfBoundsException e) { // Noncompliant {{Avoid catching Runtime exceptions : IndexOutOfBoundsException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant_2(){
+ Object obj = null;
+ try {
+ obj.toString();
+ } catch (NullPointerException e) { // Noncompliant {{Avoid catching Runtime exceptions : NullPointerException}}
+ }
+ }
+
+ public void nominalRuntimeExceptionDependant_3(){
+ try {
+ int result = 1 / 0;
+ } catch (ArithmeticException e) { // Noncompliant {{Avoid catching Runtime exceptions : ArithmeticException}}
+ }
+ }
+
+ //these exceptions are ok because they aren't runtime exceptions
+
+ public void compliantNonRuntimeException() {
+ try {
+ File file = new File("nonexistent.txt");
+ FileReader fr = new FileReader(file);
+ fr.read();
+ } catch (FileNotFoundException e) {
+ } catch (IOException e) {
+ }
+ }
+
+ // these exceptions are ok because they are IllegalArgumentExceptions, and can hardly be avoided
+
+ public void compliantIllegalArgumentException() {
+ try {
+ // some code that may throw an exception
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void compliantIllegalArgumentExceptionDependant() {
+ try {
+ Integer.parseInt("abc");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+}
diff --git a/src/test/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptionsTest.java b/src/test/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptionsTest.java
new file mode 100644
index 00000000..923f91af
--- /dev/null
+++ b/src/test/java/org/greencodeinitiative/creedengo/java/checks/AvoidCatchingRuntimeExceptionsTest.java
@@ -0,0 +1,33 @@
+/*
+ * creedengo - Java language - Provides rules to reduce the environmental footprint of your Java programs
+ * Copyright © 2024 Green Code Initiative (https://green-code-initiative.org/)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.java.checks;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.java.checks.verifier.CheckVerifier;
+
+class AvoidCatchingRuntimeExceptionsTest {
+
+ @Test
+ void test() {
+ CheckVerifier.newVerifier()
+ .onFile("src/test/files/AvoidCatchingRuntimeExceptions.java")
+ .withCheck(new AvoidCatchingRuntimeExceptions())
+ .verifyIssues();
+ }
+
+}