Hello David,
The "condition always true rule" (
squid:S2583) from the SonarJava analyzer is relying on our Symbolic Execution (SE) engine. The purpose of the engine is to explore the graph of the possible states which can occur during the execution of a method, based on its control flow graph (CFG).
I'm going to simplify a bit things to make things clear, but basically, when there is a method invocation in the body of the method, two things can happen:
- The called method is declared within the same file, and the Engine will be able to deduce a behavior of the method, based on exploration of the syntax tree, or annotations.
- The called method is declared in another file, and we (currently) do not try to deduce the full behavior of the method, but we may still learns things from the bytecode.
In any case, in both scenarios, the SE engine will look at the annotations which are used (on return values, on parameters). In the scenario you are describing, the engine deduce, that because the method is annotated with @javax.annotation.Nonnull, the return value CAN NOT be null. Consequently, the engine is able to determine by exploring all the possible states after the method invocation that the next conditions will always be true, and the issue is reported.
Now, if you switch to the other annotations, from the eclipse project, I would expect SonarLint to have the issue related to "condition always true" disappear (at least that's what I expect and observe using SonarJava 4.9 with SonarLint), but another one to appear, saying that a null dereference could be thrown.
This second behavior comes from 2 things:
- We currently do not recognize correctly the eclipse annotations, so we don't consider result of the method invocation as being necessarily non-null. This will be fixed when handling SONARJAVA-1993.
- Knowing that we do not handle the eclipse annotation correctly, the SE engine learn nothing on "var" when calling "bar.getSomething()". However, because of the test "var != null" from the next line, the SE engine learns that the returned value was potentially nullable (why making the test otherwise?). Now, because "var" is nullable, then their is risk of null dereference immediately after the if-statement, because the if statements does not discard the possibility of reaching "var.length()" with "var" being null. Consequently, we raise another issue (squid:S2259).
So to answer your question, in the case you describe, we will rely on annotations.
Hope this helps,
Michael