FP java:S2259 Optional.map()

SonarQube for IntelliJ 10.18.0.80657

I’m getting a false positive saying “map() can return null”, demonstrated with the following code:

private static Long test() {
    return Stream.of(1,2,3)
        .findFirst()
        .map(MyClass::test2)
        .orElseThrow(() -> new IllegalStateException(""));
}

private static @Nullable Long test2(Integer value) {
    if (value == 1) {
        return null;
    } else {
        return value.longValue();
    }
}

Removing the @Nullable annotation from the return value of test2() makes the issue go away, but the nullability of the return value of test2() should have no bearing on the perceived nullability of the return value of Optional.map().

EDIT: Further tinkering suggests the issue is specifically related to usage of org.jspecify.annotations.Nullable. Using jakarta.annotation.Nullable does not result in an issue being reported.

I observe the same issue in our code base using org.eclipse.jdt.annotation.Nullable .

Are these different annotations treated differently by SonarQube? We are open to move away from the eclipse annotation. But what alternative works best with SonarQube?

Kinb regards,

Hey @cmullikin and @nelkahn,

Thank you for reporting the issue and testing your setup with the Jakarta annotation for comparison. This is actually the right track to understanding how the analyzer comes to raise or not in seemingly identical situations.

The reason why we raise an issue on org.jspecify.annotations.Nullable is because it is considered a strong nullable annotation.
In contrast, jakarta.annotation.Nullable is considered a weak nullable annotation (see the annotation documentation for further detail).

However, it is not a good reason enough to raise it in this case since, as you mentioned, a null returned value, weak or strong, can be handled without any problem by Optional.map.
I created a ticket to document the issue.

Unfortunately, this ticket is unlikely to be tackled soon as we are no longer actively maintaining the symbolic execution for Java. It will however be used to benchmark our work on better dataflow analysis for a new version of S2259 or equivalent.

In the meantime, I suggest you mark this issue as a false positive and monitor the ticket to see the progress.

Thanks again for sharing this issue with us.

Cheers,

Dorian

Hey @nelkahn,

Are these different annotations treated differently by SonarQube? We are open to move away from the eclipse annotation. But what alternative works best with SonarQube?

It is difficult to give a generic answer to the question of which framework is best supported. We are interested in providing better support for jspecify annotations but as you can see in the answer above, the subtleties of the different frameworks can play nasty tricks on our existing rules.

My personal opinion (read not Sonar’s) is that jspecify annotations are worth investing in as popular frameworks such as Spring are themselves moving to use jspecify annotations.