How to resolve this warning resulting from a conflict between IntelliJ @Contract and Eclipse null analysis?

Viewed 52

I have a bit of code here that assigns what might be a null value to a @NotNull variable.

@NotNull String message = getMessage();
if (sender instanceof CommandSender) {
    message = ChatColor.stripColor(message);
}

Note that ChatColor.stripColor() can return null, which results in a warning in Eclipse.

Null type mismatch (type annotations): required '@NotNull String' but this expression has type '@Nullable String'

I solve this by checking the result from stripColor() and using a default string in the event of a null.

@Nullable String m = ChatColor.stripColor(message);
if (m == null)
    m = "";
message = m;

While I prefer to use Eclipse, the code I'm working on is being committed to a project where the author uses IntelliJ. This not uncommon, and I used their inspection tools to check for any other warnings that might not be visible in Eclipse. I was surprised to find that it had a problem with this change.

enter image description here

But how can this be? It can return null! Well, not unless the @Contract says it can. ChatColor.stripColor() is annotated with the following:

@Contract("!null -> !null; null -> null")

This is an IntelliJ annotation (org.jetbrains.annotations.Contract), and it says that if the input is non-null then the output is also non-null. And in this case, message is non-null. Eclipse can import this annotation, but it doesn't seem to be considered for null analysis.

Now I have a problem. If I don't resolve this null type mismatch, I will get an error in Eclipse. I don't want to turn this feature off, because I want to see this kind of information. But if I try to resolve it in the code, IntelliJ throws a warning because it has more information as a result of the @Contract.

Is there any way that I can satisfy the error as it appears in Eclipse and the warning as it appears in IntelliJ?

I also tried using an assertion, but IntelliJ flags this as well:

@Nullable String m = ChatColor.stripColor(message);
assert(null != m);
message = m;
1 Answers

I would try using a private method to encapsulate stripColor and make the argument nullable.

@NotNull String message = getMessage();
if (sender instanceof CommandSender) {
    message = stripColor(message);
}

...

private @NotNull String stripColor(@Nullable message) {
    String result = ChatColor.stripColor(message);
    return null == result ? "" : result;
}
Related