diff --git a/java-checks-test-sources/default/src/main/java/checks/InstantConversionsCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/DateTimeConversionsCheckSample.java similarity index 99% rename from java-checks-test-sources/default/src/main/java/checks/InstantConversionsCheckSample.java rename to java-checks-test-sources/default/src/main/java/checks/DateTimeConversionsCheckSample.java index 175c2100106..d4b6dcc19b0 100644 --- a/java-checks-test-sources/default/src/main/java/checks/InstantConversionsCheckSample.java +++ b/java-checks-test-sources/default/src/main/java/checks/DateTimeConversionsCheckSample.java @@ -16,7 +16,7 @@ import java.time.ZonedDateTime; import java.time.temporal.TemporalAccessor; -public class InstantConversionsCheckSample { +public class DateTimeConversionsCheckSample { private Instant instant; private TemporalAccessor temporalAccessor; diff --git a/java-checks/src/main/java/org/sonar/java/checks/InstantConversionsCheck.java b/java-checks/src/main/java/org/sonar/java/checks/DateTimeConversionsCheck.java similarity index 97% rename from java-checks/src/main/java/org/sonar/java/checks/InstantConversionsCheck.java rename to java-checks/src/main/java/org/sonar/java/checks/DateTimeConversionsCheck.java index 5836a8db5ac..f7fee6daeee 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/InstantConversionsCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/DateTimeConversionsCheck.java @@ -29,7 +29,7 @@ import org.sonar.plugins.java.api.tree.TypeCastTree; @Rule(key = "S8220") -public class InstantConversionsCheck extends AbstractMethodDetection implements JavaVersionAwareVisitor { +public class DateTimeConversionsCheck extends AbstractMethodDetection implements JavaVersionAwareVisitor { private static final String INSTANT = "java.time.Instant"; private static final String TEMPORAL_ACCESSOR = "java.time.temporal.TemporalAccessor"; diff --git a/java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java b/java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java index 6028ccdfaf8..5242e85d48e 100644 --- a/java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java +++ b/java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java @@ -19,11 +19,9 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import org.sonar.java.checks.InstantConversionsCheck; -import org.sonar.java.checks.helpers.MethodTreeUtils; +import org.sonar.java.checks.DateTimeConversionsCheck; import org.sonar.java.model.ExpressionUtils; import org.sonar.plugins.java.api.JavaCheck; -import org.sonar.plugins.java.api.semantic.MethodMatchers; import org.sonar.plugins.java.api.semantic.Type; import org.sonar.plugins.java.api.tree.AnnotationTree; import org.sonar.plugins.java.api.tree.Arguments; @@ -39,198 +37,211 @@ import org.sonar.plugins.java.api.tree.TypeTree; import org.sonar.plugins.java.api.tree.UnionTypeTree; -import static org.sonar.java.checks.helpers.UnitTestUtils.isTryCatchFail; +import static org.sonar.java.checks.helpers.MethodTreeUtils.consecutiveMethodInvocation; +/** + * A filter to deactivate rules that catch expressions raising specific exceptions in contexts where these exceptions are expected. + *

+ * This filter is willingly broad and works directly with type and method names rather than their types, to be resilient even in the face of missing semantic information. + *

+ */ public class ExpectedExceptionFilter extends BaseTreeVisitorIssueFilter { - private static final String ASSERTJ_ASSERTIONS = "org.assertj.core.api.Assertions"; - - private static final MethodMatchers ASSERT_THROWS_MATCHER = MethodMatchers.create() - .ofTypes("org.junit.Assert", "org.junit.jupiter.api.Assertions", "org.testng.Assert", "org.testng.AssertJUnit") - .names("assertThrows", "assertThrowsExactly", "expectThrows") - .withAnyParameters() - .build(); - - private static final MethodMatchers ASSERTJ_CATCH_THROWABLE_OF_TYPE = MethodMatchers.create() - .ofTypes(ASSERTJ_ASSERTIONS) - .names("catchThrowableOfType") - .addParametersMatcher("org.assertj.core.api.ThrowableAssert$ThrowingCallable", "java.lang.Class") - .build(); - - private static final MethodMatchers ASSERTJ_ASSERT_CODE = MethodMatchers.create() - .ofTypes(ASSERTJ_ASSERTIONS) - .names("assertThatCode", "assertThatThrownBy") - .withAnyParameters() - .build(); - - private static final MethodMatchers ASSERTJ_EXCEPTION_OF_TYPE = MethodMatchers.create() - .ofTypes(ASSERTJ_ASSERTIONS, "org.assertj.core.api.BDDAssertions") - .names("assertThatExceptionOfType", "thenExceptionOfType") - .addParametersMatcher("java.lang.Class") - .build(); - - private static final MethodMatchers ASSERTJ_TYPED_EXCEPTION = MethodMatchers.create() - .ofTypes(ASSERTJ_ASSERTIONS, "org.assertj.core.api.BDDAssertions") - .names("assertThatException", "assertThatRuntimeException", "thenException", "thenRuntimeException") - .withAnyParameters() - .build(); - - private static final MethodMatchers ASSERTJ_IS_THROWN_BY = MethodMatchers.create() - .ofTypes("org.assertj.core.api.ThrowableTypeAssert") - .names("isThrownBy") - .addParametersMatcher("org.assertj.core.api.ThrowableAssert$ThrowingCallable") - .build(); - - private static final MethodMatchers ASSERTJ_INSTANCE_OF_PREDICATES = MethodMatchers.create() - .ofSubTypes("org.assertj.core.api.Assert") - .names("isInstanceOf", "isInstanceOfAny") - .withAnyParameters() - .build(); - - private static final MethodMatchers ASSERTJ_EXACT_INSTANCE_OF_PREDICATES = MethodMatchers.create() - .ofSubTypes("org.assertj.core.api.Assert") - .names("isExactlyInstanceOf", "isOfAnyClassIn") - .withAnyParameters() - .build(); - - private static final String DATE_TIME_EXCEPTION = "java.time.DateTimeException"; - - private static final Set DATE_TIME_EXCEPTION_SUPERTYPES = Set.of( - "java.lang.RuntimeException", - "java.lang.Exception", - "java.lang.Throwable" + private static final Set DATE_TIME_EXCEPTION_TYPES = Set.of( + "DateTimeException", + "DateTimeParseException", + "RuntimeException", + "Exception", + "Throwable" + ); + + private static final Set ASSERT_THROWS_METHODS = Set.of( + "assertThrows", + "assertThrowsExactly", + "expectThrows" + ); + + private static final Set ASSERT_CODE_METHODS = Set.of( + "assertThatCode", + "assertThatThrownBy" + ); + + private static final Set INSTANCEOF_METHODS = Set.of( + "isInstanceOf", + "isInstanceOfAny", + "isExactlyInstanceOf", + "isOfAnyClassIn" + ); + + private static final Set ASSERT_EXCEPTION_METHODS = Set.of( + "assertThatException", + "assertThatRuntimeException", + "thenException", + "thenRuntimeException" + ); + + private static final Set ASSERT_OF_TYPE_METHODS = Set.of( + "assertThatExceptionOfType", + "thenExceptionOfType" ); @Override public Set> filteredRules() { - return Set.of(InstantConversionsCheck.class); + return Set.of(DateTimeConversionsCheck.class); } @Override public void visitMethod(MethodTree tree) { - if (hasExpectedDateTimeExceptionAnnotation(tree.modifiers().annotations())) { - excludeLines(tree, InstantConversionsCheck.class); + if (containsExpectedExceptions(tree.modifiers().annotations(), DATE_TIME_EXCEPTION_TYPES)) { + excludeLines(tree, DateTimeConversionsCheck.class); } super.visitMethod(tree); } @Override public void visitTryStatement(TryStatementTree tree) { - if (isTryCatchFailExpectingDateTimeException(tree)) { - excludeLines(tree.block(), InstantConversionsCheck.class); + if (catchesExpectedException(tree, DATE_TIME_EXCEPTION_TYPES)) { + excludeLines(tree.block(), DateTimeConversionsCheck.class); } super.visitTryStatement(tree); } @Override public void visitMethodInvocation(MethodInvocationTree tree) { - excludeExpectedDateTimeExceptionIssues(tree); + excludeExpectedExceptions(tree, DATE_TIME_EXCEPTION_TYPES, DateTimeConversionsCheck.class); super.visitMethodInvocation(tree); } - private void excludeExpectedDateTimeExceptionIssues(MethodInvocationTree mit) { - if (ASSERT_THROWS_MATCHER.matches(mit)) { - excludeAssertThrowsExecutableForDateTimeException(mit); - } else if (ASSERTJ_CATCH_THROWABLE_OF_TYPE.matches(mit) && isDateTimeExceptionClass(mit.arguments().get(1), false)) { - excludeLines(mit.arguments().get(0), InstantConversionsCheck.class); - } else if (ASSERTJ_ASSERT_CODE.matches(mit)) { - MethodTreeUtils.subsequentMethodInvocation(mit, ASSERTJ_INSTANCE_OF_PREDICATES).ifPresent(subsequentMit -> { - if (hasDateTimeExceptionType(subsequentMit.arguments(), false)) { - excludeLines(mit.arguments().get(0), InstantConversionsCheck.class); - } - }); - MethodTreeUtils.subsequentMethodInvocation(mit, ASSERTJ_EXACT_INSTANCE_OF_PREDICATES).ifPresent(subsequentMit -> { - if (hasDateTimeExceptionType(subsequentMit.arguments(), true)) { - excludeLines(mit.arguments().get(0), InstantConversionsCheck.class); - } - }); - } else if (ASSERTJ_TYPED_EXCEPTION.matches(mit) || (ASSERTJ_EXCEPTION_OF_TYPE.matches(mit) && isDateTimeExceptionClass(mit.arguments().get(0), false))) { - MethodTreeUtils.subsequentMethodInvocation(mit, ASSERTJ_IS_THROWN_BY).ifPresent(subsequentMit -> - excludeLines(subsequentMit.arguments().get(0), InstantConversionsCheck.class) - ); + /** + * Filter a given rule for parts of a method invocation expression when it expects a given set of exception types. + */ + private void excludeExpectedExceptions(MethodInvocationTree tree, Set expectedExceptions, Class filteredRule) { + String methodName = tree.methodSymbol().name(); + Arguments arguments = tree.arguments(); + if (ASSERT_THROWS_METHODS.contains(methodName) && arguments.size() >= 2) { + excludeFromAssertThrows(arguments, expectedExceptions, filteredRule); + } else if ("catchThrowableOfType".equals(methodName) && arguments.size() > 1 && containsExpectedExceptions(arguments.get(1), expectedExceptions)) { + excludeLines(arguments.get(0), filteredRule); + } else if (ASSERT_CODE_METHODS.contains(methodName)) { + excludeFromAssertCode(tree, arguments, expectedExceptions, filteredRule); + } else if (ASSERT_EXCEPTION_METHODS.contains(methodName) || + (ASSERT_OF_TYPE_METHODS.contains(methodName) && !arguments.isEmpty() && containsExpectedExceptions(arguments.get(0), expectedExceptions))) { + excludeIsThrownBy(tree, filteredRule); } } - private void excludeAssertThrowsExecutableForDateTimeException(MethodInvocationTree mit) { - Arguments arguments = mit.arguments(); - if (arguments.size() < 2) { - return; - } + private void excludeFromAssertThrows(Arguments arguments, Set expectedExceptions, Class filteredRule) { int expectedTypeIndex = firstArgumentIsMessage(arguments) ? 1 : 0; int executableIndex = expectedTypeIndex + 1; - if (arguments.size() > executableIndex && isDateTimeExceptionClass(arguments.get(expectedTypeIndex), "assertThrowsExactly".equals(mit.methodSymbol().name()))) { - excludeLines(arguments.get(executableIndex), InstantConversionsCheck.class); + if (arguments.size() > executableIndex && containsExpectedExceptions(arguments.get(expectedTypeIndex), expectedExceptions)) { + excludeLines(arguments.get(executableIndex), filteredRule); } } - private static boolean firstArgumentIsMessage(Arguments arguments) { - return arguments.size() >= 3 && arguments.get(0).symbolType().is("java.lang.String"); + private void excludeFromAssertCode(MethodInvocationTree tree, Arguments arguments, Set expectedExceptions, Class filteredRule) { + subsequentMethodInvocation(tree, INSTANCEOF_METHODS).ifPresent(mit -> { + if (!arguments.isEmpty() && mit.arguments().stream().anyMatch(expression -> containsExpectedExceptions(expression, expectedExceptions))) { + excludeLines(arguments.get(0), filteredRule); + } + }); } - private static boolean isTryCatchFailExpectingDateTimeException(TryStatementTree tryStatement) { - return isTryCatchFail(tryStatement.block()) && tryStatement.catches().stream().anyMatch(ExpectedExceptionFilter::isDateTimeExceptionCatch); + private void excludeIsThrownBy(MethodInvocationTree tree, Class filteredRule) { + subsequentMethodInvocation(tree, Set.of("isThrownBy")).ifPresent(mit -> { + Arguments mitArguments = mit.arguments(); + if (!mitArguments.isEmpty()) { + excludeLines(mitArguments.get(0), filteredRule); + } + }); } - private static boolean isDateTimeException(Type type, boolean exact) { - return type.isSubtypeOf(DATE_TIME_EXCEPTION) || (!exact && DATE_TIME_EXCEPTION_SUPERTYPES.stream().anyMatch(type::is)); + /** + * Check if a list of annotations contains a {@code Test} annotation expecting specific exception types. + */ + private static boolean containsExpectedExceptions(List annotations, Set expectedExceptions) { + return annotations.stream() + .anyMatch(annotation -> + "Test".equals(annotation.symbolType().name()) && containsExpectedExceptions(annotation.arguments(), expectedExceptions) + ); } - private static boolean isDateTimeExceptionClass(ExpressionTree expression, boolean exact) { - if (expression.is(Tree.Kind.NEW_ARRAY)) { - return ((NewArrayTree) expression).initializers().stream() - .anyMatch(initializer -> isDateTimeExceptionClass(initializer, exact)); + /** + * Check if a {@code Test} annotation has an {@code expected} or {@code expectedException} argument matching a set of expected exception types. + */ + private static boolean containsExpectedExceptions(Arguments arguments, Set expectedExceptions) { + return arguments.stream() + .filter(ExpectedExceptionFilter::isExpectedExceptionArgument) + .anyMatch(argument -> containsExpectedExceptions(annotationValue(argument), expectedExceptions)); + } + + /** + * Check that an annotation argument is an {@code expected} or {@code expectedException} attribute. + */ + private static boolean isExpectedExceptionArgument(ExpressionTree expression) { + String annotationAttributeName = ExpressionUtils.annotationAttributeName(expression); + return "expected".equals(annotationAttributeName) || "expectedExceptions".equals(annotationAttributeName); + } + + /** + * Check if an expression contains a given exception type. + */ + private static boolean containsExpectedExceptions(ExpressionTree expression, Set expectedExceptions) { + if (expression instanceof NewArrayTree newArray) { + return newArray.initializers().stream() + .anyMatch(initializer -> containsExpectedExceptions(initializer, expectedExceptions)); } - return classLiteralType(expression) - .map(type -> isDateTimeException(type, exact)) - .orElse(false); + return classLiteralType(expression).map(type -> expectedExceptions.contains(type.name())).orElse(false); + } + + /** + * Get the value of an annotation attribute. + */ + private static ExpressionTree annotationValue(ExpressionTree expression) { + return expression.is(Tree.Kind.ASSIGNMENT) ? ((AssignmentExpressionTree) expression).expression() : expression; } + /** + * Extract the type name of a class literal expression. + */ private static Optional classLiteralType(ExpressionTree expression) { - if (expression.is(Tree.Kind.MEMBER_SELECT)) { - MemberSelectExpressionTree memberSelect = (MemberSelectExpressionTree) expression; - if ("class".equals(memberSelect.identifier().name())) { - return Optional.of(memberSelect.expression().symbolType()); - } + if (expression instanceof MemberSelectExpressionTree memberSelect && "class".equals(memberSelect.identifier().name())) { + return Optional.of(memberSelect.expression().symbolType()); } return Optional.empty(); } - private static boolean isDateTimeExceptionCatch(CatchTree catchTree) { + /** + * Check if a try statement catches a set of expected exception types. + */ + private static boolean catchesExpectedException(TryStatementTree tryStatement, Set expectedExceptions) { + return tryStatement.catches().stream() + .anyMatch(catchTree -> catchesExpectedExceptions(catchTree, expectedExceptions)); + } + + private static boolean catchesExpectedExceptions(CatchTree catchTree, Set expectedExceptions) { return exceptionTypes(catchTree.parameter().type()).stream() - .anyMatch(type -> isDateTimeException(type.symbolType(), false)); + .anyMatch(type -> expectedExceptions.contains(type.symbolType().name())); } private static List exceptionTypes(TypeTree typeTree) { - if (typeTree.is(Tree.Kind.UNION_TYPE)) { - return ((UnionTypeTree) typeTree).typeAlternatives(); + if (typeTree instanceof UnionTypeTree unionType) { + return unionType.typeAlternatives(); } return List.of(typeTree); } - private static boolean hasExpectedDateTimeExceptionAnnotation(List annotations) { - return annotations.stream().anyMatch(annotation -> { - Type annotationType = annotation.annotationType().symbolType(); - if (annotationType.is("org.junit.Test")) { - return hasExpectedDateTimeExceptionArgument(annotation, "expected"); - } else if (annotationType.is("org.testng.annotations.Test")) { - return hasExpectedDateTimeExceptionArgument(annotation, "expectedExceptions"); - } - return false; - }); - } - - private static boolean hasExpectedDateTimeExceptionArgument(AnnotationTree annotation, String attributeName) { - return annotation.arguments().stream() - .filter(argument -> attributeName.equals(ExpressionUtils.annotationAttributeName(argument))) - .anyMatch(argument -> isDateTimeExceptionClass(annotationValue(argument), false)); - } - - private static ExpressionTree annotationValue(ExpressionTree expression) { - return expression.is(Tree.Kind.ASSIGNMENT) ? ((AssignmentExpressionTree) expression).expression() : expression; + private static boolean firstArgumentIsMessage(Arguments arguments) { + return arguments.size() >= 3 && arguments.get(0).symbolType().is("java.lang.String"); } - private static boolean hasDateTimeExceptionType(List expressions, boolean exact) { - return expressions.stream().anyMatch(expression -> isDateTimeExceptionClass(expression, exact)); + /** + * Get the next chained method invocation whose identifier matches a set of expected method names. + */ + private static Optional subsequentMethodInvocation(MethodInvocationTree tree, Set expectedMethodNames) { + return consecutiveMethodInvocation(tree) + .map(consecutiveMethod -> + expectedMethodNames.contains(consecutiveMethod.methodSymbol().name()) ? + consecutiveMethod : subsequentMethodInvocation(consecutiveMethod, expectedMethodNames).orElse(null)); } } diff --git a/java-checks/src/test/files/filters/ExpectedExceptionFilter.java b/java-checks/src/test/files/filters/ExpectedExceptionFilter.java index 312a3582d08..5fce44a726d 100644 --- a/java-checks/src/test/files/filters/ExpectedExceptionFilter.java +++ b/java-checks/src/test/files/filters/ExpectedExceptionFilter.java @@ -65,7 +65,7 @@ void junit5AssertThrowsExpectedBroadException() { org.junit.jupiter.api.Assertions.assertThrows(() -> LocalDate.from(instant)); // NoIssue org.junit.jupiter.api.Assertions.assertThrowsExactly(DateTimeException.class, () -> LocalDateTime.from(instant)); // NoIssue org.junit.jupiter.api.Assertions.assertThrowsExactly(DateTimeParseException.class, () -> LocalDateTime.from(instant)); // NoIssue - org.junit.jupiter.api.Assertions.assertThrowsExactly(RuntimeException.class, () -> LocalDateTime.from(instant)); // WithIssue + org.junit.jupiter.api.Assertions.assertThrowsExactly(RuntimeException.class, () -> LocalDateTime.from(instant)); // NoIssue } @org.junit.jupiter.api.Test @@ -93,9 +93,9 @@ void testngExpectThrows() { void assertjAssertThatThrownBy() { org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isInstanceOf(DateTimeException.class); // NoIssue org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isInstanceOf(RuntimeException.class); // NoIssue - org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isInstanceOf(IllegalArgumentException.class); // WithIssue - org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isExactlyInstanceOf(RuntimeException.class); // WithIssue + org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isExactlyInstanceOf(RuntimeException.class); // NoIssue org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isExactlyInstanceOf(DateTimeException.class); // NoIssue + org.assertj.core.api.Assertions.assertThatThrownBy(() -> Instant.from(date)).isInstanceOf(IllegalArgumentException.class); // WithIssue } @org.junit.jupiter.api.Test @@ -112,6 +112,7 @@ void assertjExceptionOfType() { @org.junit.jupiter.api.Test void assertjCatchThrowableOfType() { org.assertj.core.api.Assertions.catchThrowableOfType(() -> OffsetTime.from(instant), DateTimeException.class); // NoIssue + org.assertj.core.api.Assertions.catchThrowableOfType(() -> Instant.from(date), IllegalArgumentException.class); // WithIssue } @org.junit.jupiter.api.Test @@ -151,6 +152,50 @@ void tryCatchFail() { } catch (DateTimeException | IllegalArgumentException e) { // expected } + + try { + LocalDate.from(instant); // NoIssue + } catch (DateTimeException e) { + // expected + } + } + + // When semantic information is missing, the filter should conservatively activate. + @Test(expected = RuntimeException.class) + void expectedMethodAnnotationWithoutSemantics() { + Instant.from(date); // NoIssue + } + + @Test(expectedExceptions = DateTimeException.class) + void expectedExceptionsMethodAnnotationWithoutSemantics() { + Instant.from(date); // NoIssue + } + + @Test + void methodInvocationsWithoutSemantics() { + // Here too, the filter should activate even though no semantic information is available. + assertThrows(DateTimeException.class, () -> LocalDate.from(instant)); // NoIssue + assertThatThrownBy(() -> Instant.from(date)).isInstanceOf(DateTimeException.class); // NoIssue + assertThatExceptionOfType(DateTimeException.class).isThrownBy(() -> ZonedDateTime.from(dateTime)); // NoIssue + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> ZonedDateTime.from(dateTime)); // WithIssue + assertThatIllegalArgumentException().isThrownBy(() -> Instant.from(date)); // WithIssue + thenRuntimeException().isThrownBy(() -> Instant.from(date)); // NoIssue + } + + @Test(expected = DateTimeException) + void wrongExpectedType() { + Instant.from(date); // WithIssue + } + + @Test(expect = DateTimeException.class) + void wrongAnnotationAttribute() { + Instant.from(date); // WithIssue + } + + @Test + void wrongAssertMethodSignature() { + assertThrows(Instant.from(date)); // WithIssue + catchThrowableOfType(Instant.from(date)); // WithIssue } } diff --git a/java-checks/src/test/java/org/sonar/java/checks/InstantConversionsCheckTest.java b/java-checks/src/test/java/org/sonar/java/checks/DateTimeConversionsCheckTest.java similarity index 84% rename from java-checks/src/test/java/org/sonar/java/checks/InstantConversionsCheckTest.java rename to java-checks/src/test/java/org/sonar/java/checks/DateTimeConversionsCheckTest.java index e7ecfdb8e60..2b99e62c0e6 100644 --- a/java-checks/src/test/java/org/sonar/java/checks/InstantConversionsCheckTest.java +++ b/java-checks/src/test/java/org/sonar/java/checks/DateTimeConversionsCheckTest.java @@ -21,13 +21,13 @@ import static org.sonar.java.checks.verifier.TestUtils.mainCodeSourcesPath; -class InstantConversionsCheckTest { +class DateTimeConversionsCheckTest { @Test void test() { CheckVerifier.newVerifier() - .onFile(mainCodeSourcesPath("checks/InstantConversionsCheckSample.java")) - .withCheck(new InstantConversionsCheck()) + .onFile(mainCodeSourcesPath("checks/DateTimeConversionsCheckSample.java")) + .withCheck(new DateTimeConversionsCheck()) .verifyIssues(); } } diff --git a/java-checks/src/test/java/org/sonar/java/filters/ExpectedExceptionFilterTest.java b/java-checks/src/test/java/org/sonar/java/filters/ExpectedExceptionFilterTest.java index e6c18c8fc06..4d2e67a007f 100644 --- a/java-checks/src/test/java/org/sonar/java/filters/ExpectedExceptionFilterTest.java +++ b/java-checks/src/test/java/org/sonar/java/filters/ExpectedExceptionFilterTest.java @@ -26,4 +26,11 @@ void test() { .verify("src/test/files/filters/ExpectedExceptionFilter.java", new ExpectedExceptionFilter()); } + @Test + void test_without_semantics() { + FilterVerifier.newInstance() + .withoutSemantic() + .verify("src/test/files/filters/ExpectedExceptionFilter.java", new ExpectedExceptionFilter()); + } + }