Skip to content

SONARJAVA-6305 Fix the expected exceptions filter to work without semantic information#5626

Open
aurelien-coet-sonarsource wants to merge 8 commits into
masterfrom
ac/SONARJAVA-6305-2
Open

SONARJAVA-6305 Fix the expected exceptions filter to work without semantic information#5626
aurelien-coet-sonarsource wants to merge 8 commits into
masterfrom
ac/SONARJAVA-6305-2

Conversation

@aurelien-coet-sonarsource
Copy link
Copy Markdown
Contributor

@aurelien-coet-sonarsource aurelien-coet-sonarsource commented May 22, 2026


Summary by Gitar

  • Refactored checks:
    • Renamed InstantConversionsCheck to DateTimeConversionsCheck to reflect its broadened scope.
  • Implemented new logic:
    • Added detection for invalid date-time conversions involving LocalDate, LocalTime, and ZonedDateTime types.
    • Enhanced ExpectedExceptionFilter to allow these conversions to work correctly without full semantic information.
  • Expanded test coverage:
    • Added DateTimeConversionsCheckSample and DateTimeConversionsCheckTest to verify the new detection logic.
    • Added additional test cases in ExpectedExceptionFilter.java to validate filter behavior with various exception types and signatures.

This will update automatically on new commits.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 22, 2026

Agentic Analysis: Early Results

Agentic Analysis and Context Augmentation are available on your project. Here are some issues that could have been prevented. Follow the links to learn how to put them into action.

5 issue(s) found across 1 file(s):

Rule File Line Message
java:S2201 java-checks/src/test/files/filters/ExpectedExceptionFilter.java 157 The return value of "from" must be used.
java:S2201 java-checks/src/test/files/filters/ExpectedExceptionFilter.java 166 The return value of "from" must be used.
java:S2201 java-checks/src/test/files/filters/ExpectedExceptionFilter.java 171 The return value of "from" must be used.
java:S2201 java-checks/src/test/files/filters/ExpectedExceptionFilter.java 187 The return value of "from" must be used.
java:S2201 java-checks/src/test/files/filters/ExpectedExceptionFilter.java 192 The return value of "from" must be used.

Analyzed by SonarQube Agentic Analysis in 5.5 s

@hashicorp-vault-sonar-prod
Copy link
Copy Markdown
Contributor

hashicorp-vault-sonar-prod Bot commented May 22, 2026

SONARJAVA-6305

Comment thread java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java Outdated
Comment thread java-checks/src/test/files/filters/ExpectedExceptionFilter.java Outdated
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented May 26, 2026

Code Review ✅ Approved 2 resolved / 2 findings

Refactored the expected exceptions filter to function without semantic information and renamed the conversion check to broaden its scope. Addressed an unchecked argument index access and a duplicate test method name.

✅ 2 resolved
Quality: Duplicate method name in test file

📄 java-checks/src/test/files/filters/ExpectedExceptionFilter.java:158 📄 java-checks/src/test/files/filters/ExpectedExceptionFilter.java:162
The test file defines two methods both named methodAnnotationWithoutSemantics (lines 158 and 162). While Java allows method overloading, these methods have the same signature (both take no arguments and return void), which will cause a compilation error.

Edge Case: Unchecked argument index access may throw IndexOutOfBoundsException

📄 java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java:128 📄 java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java:137-138 📄 java-checks/src/main/java/org/sonar/java/filters/ExpectedExceptionFilter.java:130-135
The refactoring replaced MethodMatchers (which validated parameter count via addParametersMatcher) with name-based matching, but didn't add equivalent bounds checks on argument lists. If a method with the same name but a different signature is encountered (plausible since this is name-only matching), arguments.get(1) or arguments.get(0) will throw IndexOutOfBoundsException.

Three sites are affected:

  • Line 128: catchThrowableOfType accesses arguments.get(1) without checking arguments.size() >= 2
  • Line 137: assertThatExceptionOfType/thenExceptionOfType accesses arguments.get(0) without checking non-empty
  • Line 138: isThrownBy accesses mit.arguments().get(0) without checking non-empty

Since the filter now intentionally matches by name alone, it's more likely to encounter unexpected method signatures.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@NoemieBenard NoemieBenard left a comment

Choose a reason for hiding this comment

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

Overall LGTM and should work for the FPs that we have, just some comments

}
}

// When semantic information is missing, the filter should conservatively activate.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is it really about semantic here ?

Comment on lines +185 to +198
@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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if we are not being too strict with these tests, we could prevent the filter from activating on patterns that we don't recognize even though they are correct. (but maybe we can keep it as it is for now, WDYT?)

Comment on lines 208 to 213
if (expression.is(Tree.Kind.MEMBER_SELECT)) {
MemberSelectExpressionTree memberSelect = (MemberSelectExpressionTree) expression;
if ("class".equals(memberSelect.identifier().name())) {
return Optional.of(memberSelect.expression().symbolType());
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks nicer IMO:

Suggested change
if (expression instanceof MemberSelectExpressionTree memberSelect
&& "class".equals(memberSelect.identifier().name())) {
return Optional.of(memberSelect.expression().symbolType());
}

import org.sonar.plugins.java.api.tree.UnionTypeTree;

import static org.sonar.java.checks.helpers.MethodTreeUtils.consecutiveMethodInvocation;
import static org.sonar.java.checks.helpers.UnitTestUtils.isTryCatchFail;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The unused import should be removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants