10

I'm developing with Android Studio/IntelliJ IDEA.

I have enabled the inspection check called "Constant conditions & exceptions" that shows a warning if I am risking a NPE, such as:

String foo = foo.bar(); // Foo#bar() is @nullable
if (foo.contains("bar")) { // I'm living dangerously
    ...
}

I have the following in my code:

String encoding = contentEncoding == null ? null : contentEncoding.getValue();
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
    inputStream = new GZIPInputStream(entity.getContent());
} else {
    inputStream = entity.getContent();
}

Here's the source code of TextUtils#isEmpty(String):

/**
 * Returns true if the string is null or 0-length.
 * @param str the string to be examined
 * @return true if str is null or zero length
 */
public static boolean isEmpty(CharSequence str) {
    if (str == null || str.length() == 0)
        return true;
    else
        return false;
}

I'm not risking any NPE because TextUtils#isEmpty(String) would return true to a null pointer.

However I'm still getting the little Method invocation 'encoding.equalsIgnoreCase("gzip")' may produce 'java.lang.NullPointerException' warning, which can be annoying.

Is it possible to make this check smarter and ignore the NPE warning if there's already a null-check done?

Pang
  • 9,564
  • 146
  • 81
  • 122
Benoit Duffez
  • 11,839
  • 12
  • 77
  • 125
  • 1
    You could circumvent this by typing `"gzip".equalsIgnoreCase(encoding)` instead. – maba Oct 11 '13 at 10:41
  • You're absolutely right, but it's not always `String#equals`. For example `foo.contains(bar)`, both being pointers: it can warn about foo being nullable, while the null check has already been done by `TextUtils#isEmpty` – Benoit Duffez Oct 11 '13 at 12:16

6 Answers6

19

You can look into the link that Peter Gromov mention in his answer.

Created some simple classes that resemble your setup:

A class with a method annotated with @Nullable:

enter image description here

The TextUtil class with it's isEmpty method:

enter image description here

And finally the main class calling the TextUtil#isEmpty:

enter image description here

Now if you enter the File -> Settings... and go to Inspections ->Constant conditions & exceptions part you can change the Configure Assert/Check Methods to cater for your isEmpty method:

enter image description here

Add a new IsNull check method:

enter image description here

Enter the TextUtil class, isEmpty method and CharSequence parameter:

enter image description here

This gives this Assert/Check Method Configuration window:

enter image description here

Press Ok and then Ok again to go back to the editor view and you'll see that the inspection disappeared:

enter image description here

You are actually telling IntelliJ that the isEmpty method is doing a null check on the str parameter.

Community
  • 1
  • 1
maba
  • 47,113
  • 10
  • 108
  • 118
10

You could use //noinspection ConstantConditions that will remove the NPE warning for the following line, like this:

String encoding = contentEncoding == null ? null : contentEncoding.getValue();

//noinspection ConstantConditions
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
    inputStream = new GZIPInputStream(entity.getContent());
} else {
    inputStream = entity.getContent();
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Olivier Payen
  • 15,198
  • 7
  • 41
  • 70
6

You can use @SuppressWarnings("ConstantConditions") annotation.

@SuppressWarnings("ConstantConditions")
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int indexViewType) {
    if (inflater == null) {
        inflater = LayoutInflater.from(parent.getContext());
    }
    ItemViewProvider provider = getProviderByIndex(indexViewType);
    provider.adapter = MultiTypeAdapter.this;
    return provider.onCreateViewHolder(inflater, parent);
}
Pang
  • 9,564
  • 146
  • 81
  • 122
jk2K
  • 4,279
  • 3
  • 37
  • 40
  • Don't suppress it on a wide range of code like this: 1) there's no way to tell what you're actually suppressing (can `provider` be null, or `parent`, or `inflater`, ...?); 2) it disables checks for any future code in that range (even an explicit `((Object) null).toString();` will not warn about the null-access, if added to this method) – TWiStErRob Sep 29 '17 at 10:27
3
  1. Select "TextUtils.isEmpty".
  2. Right Click -> Show Context Actions -> Add Method Contract.
  3. Enter "null -> true".
  4. Save the configuration xml.

Please check the details here

1

See http://www.jetbrains.com/idea/webhelp/configuring-check-assert-methods.html for IDEA 12. In IDEA 13 EAP, you can add method contract: http://youtrack.jetbrains.com/issue/IDEA-93372

Peter Gromov
  • 17,615
  • 7
  • 49
  • 35
1

Unfortunately marked as "right answer" solution is of date. But I found equivalent for me solution.

The new versions of IDE work correctly with static methods. So the example from the question won't throw warning anymore.

TextUtils#isEmpty(String);

public static boolean isEmpty(CharSequence str) {
    // your checks
}
VKostenc
  • 1,140
  • 14
  • 19