Hi team,
Testing sonar-java with semantics-preserving rewrites, we found that S1862 (“Related `if/else if` statements should not have the same condition”) misses
duplicate conditions when one branch writes the condition in an equivalent form.
This is partly known. SONARJAVA-4111 (thread:
https://community.sonarsource.com/t/java-a-false-negative-about-the-rule-rspec-1862/55025) added normalization for two shapes, `==` operand reversal (`a == b` vs
`b == a`) and redundant parentheses (`a` vs `(a)`), and both fire on the version
below. The same ticket raised a follow-up (Alban Auzeill: *“we could create a
ticket to support `!=` which is also commutative, or even `>`, `>=`, `<`, `<=`
that can be reverted.”*). That follow-up appears never to have been implemented:
operand reversal for `!=`, `>`, `>=`, `<`, `<=` is still a false negative, though it is the same class as the `==` case already handled.
**Product / version:** SonarQube Community Build 26.7.0.124771 (the current latest), sonar-scanner 8.1.0.6389, “Sonar way” profile.
Type: false negative.
Reproducer:
public class S1862Repro {
void foo(int a, int b) {
if (a > b) {
System.out.println(1);
} else if (b < a) { // Noncompliant: same condition as \`a > b\`, S1862 should report here
System.out.println(2);
}
}
}
Expected: a warning on the `else if (b < a)` branch, as it now reports for the `==` reversal.
### Shapes tested on CB 26.7.0.124771
Each row is the same condition in both branches, differing only by an equivalent
rewrite. We are asking only about rows 3-5; the rest records the current
boundary.
| # | rewrite | SONARJAVA-4111 | S1862 today |
|—|---------|----------------|-------------|
| 1 | `a == b` ↔ `b == a` (`==` reversal) | fixed | fires |
| 2 | `a` ↔ `(a)` / `((a))` (redundant parens) | fixed | fires |
| 3 | `a != b` ↔ `b != a` (`!=` reversal) | deferred follow-up | **FN** |
| 4 | `a > b` ↔ `b < a` (`>`/`<` reversal) | deferred follow-up | **FN** |
| 5 | `a >= b` ↔ `b <= a` (`>=`/`<=` reversal) | deferred follow-up | **FN** |
| 6 | `a` ↔ `!(!a)` (double negation) | declined, “complex” | FN |
| 7 | `a != b` ↔ `!(a == b)` (negation into comparison) | declined, “complex” | FN |
Rows 6-7 are the “more complex cases” the ticket declined (“we will not extend the logic to support more complex cases”). We are not requesting them; they mark the boundary.
We also left out `a && b` ↔ `b && a`, since `&&`/`||` short-circuit and reversing the operands is not always behaviour-preserving. Happy to provide more reproducers if useful.