Skip to content

Commit

Permalink
ignore thrown exceptions in utility class constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
Luro02 committed Apr 4, 2024
1 parent 690fc70 commit a14a755
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtThrow;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtElement;

import java.util.List;
Expand Down Expand Up @@ -41,6 +42,16 @@ private static boolean hasMessage(List<? extends CtExpression<?>> arguments) {
}

private static boolean isInAllowedContext(CtElement ctElement) {
// allow exceptions without messages in utility classes:
//
// private MyUtilityClass {
// throw new UnsupportedOperationException();
// }
CtConstructor<?> ctConstructor = ctElement.getParent(CtConstructor.class);
if (ctConstructor != null && ctConstructor.isPrivate()) {
return true;
}

CtCase<?> ctCase = ctElement.getParent(CtCase.class);
// allow no message in default case of switch (most likely used as an unreachable default case)
// See: https://github.com/Feuermagier/autograder/issues/82
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package de.firemage.autograder.core.check.exceptions;

import de.firemage.autograder.core.LinterException;
import de.firemage.autograder.core.LocalizedMessage;
import de.firemage.autograder.core.Problem;
import de.firemage.autograder.core.ProblemType;
import de.firemage.autograder.core.check.AbstractCheckTest;
import de.firemage.autograder.core.compiler.JavaVersion;
import de.firemage.autograder.core.file.StringSourceInfo;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

class TestExceptionMessageCheck extends AbstractCheckTest {
private static final List<ProblemType> PROBLEM_TYPES = List.of(ProblemType.EXCEPTION_WITHOUT_MESSAGE);

void assertMissingMessage(Problem problem) {
assertEquals(
this.linter.translateMessage(new LocalizedMessage(
"exception-message"
)),
this.linter.translateMessage(problem.getExplanation())
);
}

@Test
void testUtilityClassConstructor() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
public class Main {
private Main() {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
}
}
"""
), PROBLEM_TYPES);

problems.assertExhausted();
}

@Test
void testCustomException() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
class Bar extends Exception {
public Bar() {
super("Bar");
}
}
public class Main {
void foo() throws Bar {
throw new Bar(); /*# ok #*/
}
}
"""
), PROBLEM_TYPES);

problems.assertExhausted();
}

@Test
void testEmptyMessageString() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
public class Main {
void c() {
throw new IllegalArgumentException(""); /*# not ok #*/
}
void d() {
throw new IllegalArgumentException(" "); /*# not ok #*/
}
void f() {
throw new IllegalArgumentException("", new Exception()); /*# not ok #*/
}
}
"""
), PROBLEM_TYPES);

assertMissingMessage(problems.next());
assertMissingMessage(problems.next());
assertMissingMessage(problems.next());

problems.assertExhausted();
}

@Test
void testExceptionMessage() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
public class Main {
void a() {
throw new IllegalArgumentException("foo"); /*# ok #*/
}
void b() {
throw new IllegalArgumentException(); /*# not ok #*/
}
}
"""
), PROBLEM_TYPES);

assertMissingMessage(problems.next());

problems.assertExhausted();
}

@Test
void testSwitchDefault() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
public class Main {
void foo(String string) {
switch (string) {
case "a" -> {}
case "b" -> {}
default -> throw new IllegalStateException(); /*# ok #*/
}
}
}
"""
), PROBLEM_TYPES);

problems.assertExhausted();
}

@Test
void testExceptionCatchAndThrow() throws IOException, LinterException {
ProblemIterator problems = this.checkIterator(StringSourceInfo.fromSourceString(
JavaVersion.JAVA_17,
"Main",
"""
public class Main {
private java.io.File file;
public String[] readFile() {
try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(this.file))) {
return reader.lines().toArray(String[]::new);
} catch (final java.io.IOException e) {
throw new RuntimeException(e); /*# ok #*/
}
}
}
"""
), PROBLEM_TYPES);

problems.assertExhausted();
}
}

This file was deleted.

This file was deleted.

0 comments on commit a14a755

Please sign in to comment.