What language is this for?
Java
Which rule?
- Rule Key:
java:S2200 - Rule Name: “compareTo” results should not be checked for specific values
Why do you believe it’s a false-negative?
According to the Comparable contract and the rule documentation, the result of compareTo() should only be checked for its sign (> 0, < 0, or == 0). Checking for specific numeric values such as 1 or -1 is unreliable because the exact magnitude is an implementation detail and can vary between classes, JDK versions, or even different compareTo implementations.
The current rule correctly detects direct calls and variable references:
if (a.compareTo(b) == 1) { ... } // detected
int result = a.compareTo(b);
if (result == 1) { ... } // detected
However, it completely misses cases where the compareTo() result is wrapped in a type cast (Tree.Kind.TYPE_CAST), which is a very common pattern in real code (explicit casts for clarity, autoboxing, or legacy code).
The following patterns are not detected at all (False Negative), even though they have exactly the same runtime semantics as the cases the rule already catches.
Are you using
-
SonarQube Server / Community Build - latest version
-
SonarJava analyzer - latest version
(I am not using SonarQube Cloud or SonarQube for IDE in this report.)
How can we reproduce the problem?
Here is a self-contained, fully compilable Java 8+ snippet:
Java
import java.util.Comparator;
public class S2200FalseNegativeDemo {
static class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
public static void main(String[] args) {
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Bob", 30);
// ❌ These three cases are NOT detected (False Negative)
if ((int) p1.compareTo(p2) == 1) { // should raise java:S2200
System.out.println("p1 is greater");
}
if ((Integer) p1.compareTo(p2) == -1) { // should raise java:S2200
System.out.println("p1 is less");
}
if (((int) p1.compareTo(p2)) == 1) { // should raise java:S2200
System.out.println("p1 is greater");
}
// ✅ Only these patterns are currently detected
if (p1.compareTo(p2) == 1) { } // detected
}
}
Expected behavior: All three type-cast cases above should raise java:S2200.
Additional technical detail (for the development team):
The root cause is in CompareToResultTestCheck.java:
Java
private static boolean isCompareToResult(ExpressionTree expression) {
if (expression.is(Tree.Kind.METHOD_INVOCATION)) {
return COMPARE_TO.matches((MethodInvocationTree) expression);
}
if (expression.is(Tree.Kind.IDENTIFIER)) {
return isIdentifierContainingCompareToResult((IdentifierTree) expression);
}
return false; // ← no handling for Tree.Kind.TYPE_CAST
}
visitNode only calls ExpressionUtils.skipParentheses() and never skips or recurses into type casts. The check should use (or implement) logic similar to ExpressionUtils.skipParenthesesAndCasts() to extract the inner compareTo call.
I searched the SonarSource community forum and both sonar-java / sonarqube GitHub repositories before posting — no existing issue matches this specific false negative scenario.
Thank you for your help!
text