sonarLint complains "Null pointers should not be dereferenced (squid:S2259)" despite that possibility being handled
Asked Answered
C

2

7

So I have an issue with SonarLint that I am not sure how to approach.

let's say I have a class with a method

public class Class(RemoteContext context)
    RemoteContext context = context;

    public void String method(String data) {
        if(data == null)
            context.raiseException("data can't be null");

        //do stuff with data like data.get();
    }

When I analyze this class with sonarLint (3.2.) I get a Null pointer should not be dereferenced issue.

So my question is. How to solve this issue? context.RaiseException will stop method execution so I think it is a false positive.

The application has a lot of cases (classes/methods) with this problem. So I'm thinking that annotations are an overkill (ugly code all around) I could also type return after each raiseException() call, but I'm under the impression that is not the "programmers way".

I'm guessing writing my own rule would be best.

I was looking over the topics and did me googling around but did not find anything useful for this case, when I sort of having to do the "opposite" of what sonar actually does. Not raising an issue, but kind of "giving a green light" on the method?

Hopefully, I was clear enough on the issue.

Cyrene answered 28/11, 2017 at 14:50 Comment(6)
What is the signature of the RemoteContext#raiseException method?Robers
More than one. 6 different ones to be preciseCyrene
Only one of which is being used above, and thus relevant.Robers
public void raiseException(int Status, String logMessage, String messageID, Map errorMessages)Cyrene
Yes it throws a RunTimeException, sorry i didnt catch on first what you wantedCyrene
"context.RaiseException will stop method execution": but sonarLint can't know that.Ma
R
6

If RemoteContext is a class you control, and you really don't want to use the usual new ExceptionType(...) pattern, I would change RemoteContext to build the exception but not throw it, and then

if (data == null) {
    throw context.buildException("data can't be null");
}

...so that it's clear to SonarLint, to the Java compiler, and to programmers doing work on the code later that execution of the method stops at that point (since "raise exception" can mean a lot of things).

(Yes, this means changing the lots of places you have this, but a relatively simply search-and-replace achieves that.)

Robers answered 28/11, 2017 at 14:55 Comment(3)
Not really under my control, doubt this approach is possibleCyrene
@user3219947: Well, at that point you're into doing a workaround for poor practices; the Java compiler, SonarLint, and people doing maintenance later can't know the method execution ends there (except by inference, knowing the raiseException method name). Adding a return; after it seems like your second best (by a large margin) solution.Robers
Lines up with my idea ... should have read your answer first ;-)Chirk
C
2

There aren't really elegant ways to solve this. What does work:

 public SomeException createAndThrow() {
   throw new SomeException();
 }

To be used like:

 throw createAndThrow();

That gives you like "double locking":

  • your utility method throws ... but in case it would not throw
  • you assume that an exception object is simply returned, so lets throw that one

Other languages, such as C++ even allow to express: this method/function is not support to return normally. But Java doesn't offer that.

Chirk answered 28/11, 2017 at 15:10 Comment(2)
Ooooh, that's really clever -- and possibly nefarious. I need to think more on it... :-)Robers
Of course, if someone does return null the whole thing probably breaks in very ugly ways.Chirk

© 2022 - 2024 — McMap. All rights reserved.