Version 6.7.4 (build 38452)
SonarJava 5.5 (build 14655)
reproduction example:
package sonar.failure;
import java.util.Random;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
// these annotations are available from https://search.maven.org/#artifactdetails%7Corg.eclipse.jdt%7Corg.eclipse.jdt.annotation%7C2.2.0%7Cjar, but you probably know those, since they are part of your null analysis
@NonNullByDefault
public class SonarqubeFailureReproduction {
public void failure() {
final String nullOrNot = nullOrNonNullMethod(new Random().nextBoolean() ? "foo" : null);
if (nullOrNot == null) {
System.out.println(
"Sonar says this line cannot be reached because the condition is always false. That is wrong.");
}
}
@Nullable
private String nullOrNonNullMethod(@Nullable final String arg) {
if (arg == null) {
return null;
}
return nonNullMethod(arg); // the root cause is this line. Sonar concludes that the complete method
// nullOrNonNullMethod() always returns nonNull because of this line.
}
@NonNull
private String nonNullMethod(final String arg) {
return "" + arg;
}
}
The conclusioning of Sonar marks these 5 places with red markers:
1 āā + arg
Implies āargā is not null.
2 nonNullMethod(arg)
ānonNullMethod()ā returns not null.
3 nullOrNonNullMethod(Randomā¦)
ānullOrNonNullMethod()ā can return not null.
4 final String nullOrNot
Implies ānullOrNotā can be not null.
5 nullOrNot == null
Expression is always false.