Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please change ID GCI96 to GCI98 in all this PR, because PR green-code-initiative/creedengo-rules-specifications#401 has just been merged


### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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) {
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public class JavaCheckRegistrar implements CheckRegistrar {
FreeResourcesOfAutoCloseableInterface.class,
AvoidMultipleIfElseStatement.class,
UseOptionalOrElseGetVsOrElse.class,
MakeNonReassignedVariablesConstants.class
MakeNonReassignedVariablesConstants.class,
AvoidCatchingRuntimeExceptions.class
);

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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<Kind> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"GCI78",
"GCI79",
"GCI82",
"GCI94"
"GCI94",
"GCI96"
]
}
91 changes: 91 additions & 0 deletions src/test/files/AvoidCatchingRuntimeExceptions.java
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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) {
}
}

}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}

}
Loading