SONARJAVA-6685 Implement new rule S1944 - #5842
Conversation
Detect inappropriate type casts that will always fail at runtime with a ClassCastException. The rule flags casts between unrelated concrete classes and casts between a final class and an unrelated interface.
There was a problem hiding this comment.
It looks like this was done using the wrong version of rule-api
| if (areNeitherInterfaces(sourceType, targetType) || areTypesFinalClassAndInterface(sourceType, targetType)) { | ||
| reportIssue(castTree.type(), | ||
| String.format("\"%s\" cannot be cast to \"%s\" without a risk of \"ClassCastException\".", | ||
| sourceType.name(), targetType.name())); | ||
| } |
There was a problem hiding this comment.
🚨 Bug: Rule only matches casts that are compile-time errors
Every Noncompliant case detected by the two conditions in visitNode (areNeitherInterfaces = both are concrete classes; areTypesFinalClassAndInterface = a final class vs. an unrelated interface) is rejected by the Java compiler itself as "inconvertible types". I compiled the six Noncompliant samples with javac and all six fail to compile (Dog→Car, String→Dog, FinalDog→Vehicle, Vehicle→FinalDog, Color→Size, Color→Drawable). Since SonarJava only analyzes code that compiles, this rule can effectively never raise an issue on a real project, and the test sample file (InappropriateCastCheckSample.java) does not compile. A working S1944 must target casts that DO compile but fail at runtime (e.g. generic-argument casts via erasure, or interface→non-final-class casts where the concrete object is unrelated), not casts already forbidden by the compiler.
Was this helpful? React with 👍 / 👎
| <h3>Noncompliant code example</h3> | ||
| <pre> | ||
| public class S1944 { | ||
|
|
||
| public static void main(String[] args) { | ||
| List<String> list = (List<String>) getAttributes(); // Noncompliant; List<Integer> return by getAttributes() is not be casted to List<String> | ||
| String s = list.get(0); // java.lang.ClassCastException will be raised here | ||
| } | ||
|
|
||
| private static List<?> getAttributes() { | ||
| List<Integer> result = new ArrayList<>(); | ||
| result.add(0); | ||
| return result; | ||
| } | ||
|
|
There was a problem hiding this comment.
⚠️ Quality: Implementation contradicts documented S1944 behavior
S1944.html documents the rule as flagging generic casts that fail at runtime, e.g. (List<String>) getAttributes() where the actual value is a List<Integer>. The implementation uses erasure() and explicitly treats exactly this scenario as Compliant (sample line 81: (List<String>) wildcardList). So the shipped documentation describes a case the code never detects, while the code detects only compile-error casts the docs never mention. Align the implementation with the documented intent (or update the HTML/JSON to reflect the actual, narrower behavior) before this leaves draft.
Was this helpful? React with 👍 / 👎
There was a problem hiding this comment.
Comment gitar unblock to override this block and allow merging.
Configure merge blocking · Maintainers can dismiss this review.
|
❌ Ruling needs updating. A fix PR has been created: #5843 Please review and merge it into your branch. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
❌ Ruling needs updating. A fix PR has been created: #5843 Please review and merge it into your branch. |
|
It looks like to raise anything useful, we would need some dataflow analysis, so I'll not implement this rule right now. |
CI failed: Integration test failures occurred due to unexpected issue differences in the Java ruling tests (eclipse_jetty_incremental) introduced by the new rule S1944 implementation, along with missing directories in autoscan tests.OverviewAnalysis of 12 CI logs across parallel jobs identified test failures related to the implementation of new rule S1944 in FailuresJavaRulingTest Issue Differences (confidence: high)
Autoscan Integration Test Missing Directory (confidence: high)
Summary
Code Review 🚫 Blocked 0 resolved / 2 findingsImplements rule S1944 to detect inappropriate type casts, but the current logic only matches casts that are already compile-time errors and contradicts documented behavior. 🚨 Bug: Rule only matches casts that are compile-time errors📄 java-checks/src/main/java/org/sonar/java/checks/InappropriateCastCheck.java:49-53 📄 java-checks/src/main/java/org/sonar/java/checks/InappropriateCastCheck.java:66-73 📄 java-checks-test-sources/default/src/main/java/checks/InappropriateCastCheckSample.java:24-38 Every Noncompliant case detected by the two conditions in visitNode (
|
| Auto-apply | Compact | Unblock |
|
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Detect inappropriate type casts that will always fail at runtime with a ClassCastException. The rule flags casts between unrelated concrete classes and casts between a final class and an unrelated interface.
Part of