简体   繁体   中英

How to make IntelliJ IDEA warn when null might be returned from lambda?

There are very useful code inspections in IntelliJ IDEA Constant conditions & exceptions and Return of 'null' . They show warnings when a method without @Nullable annotation returns null , a result of @Nullable method, @Nullable field or variable which might evaluate to null .

Unfortunately, the same not work with lambda expressions. IntelliJ IDEA just ignores possible returning of null from them. But I am pretty sure that there is a way to make Search Template for Structural Search Inspection which will find all possible returnings null from lambda expressions.

By this moment I've managed to make a template which finds references to @Nullable methods and template that wraps single-line lambdas with a method accepting @NotNull generic argument and returning it back, it doesn't change code semantics and shows warnings when lambda might return null.

Here are my templates:

Nullable methods:

@Nullable
$MethodType$ $Method$($ParameterType$ $Parameter$);

Nullable method references

$Qualifier$::$Method$

//Filters for $Method$:
reference = Nullable methods

Lambdas with unchecked result:

($Parameter$) -> $Statement$

//Filters for $Statement$:
text = !warnIfNull
type = !void|Optional|int|boolean|long|char|short|byte

//Replace template for $Statement$:
WarnUtils.warnIfNull($Statement$)

WarnUtils:

@UtilityClass
public class WarnUtils {
    public <T> @NotNull T warnIfNull(@NotNull T t) {
        return t;
    }
}

I don't know how to make a template for multiline lambdas and I don't like wrapping all single-line lambdas with an additional method.

I think script filters may help, but I have no idea what to do with __context__ to check whether lambda probably returns null.

This problem can be solved without additional code inspections just by using functional interface which has @NotNull annotation on its abstract method.

For example, if you need a supplier which mustn't return null you can use this interface:

@FunctionalInterface
public interface NotNullSupplier<T> {
    @NotNull
    T get();
}

If you try to return null from lambda expression of this type, Constant conditions & exceptions or Return of 'null' code inspection will detect it:

NotNullSupplier<Integer> supplier = () -> null; // warning - 'null' is returned by the method declared as @NotNull

I want to notice that using Supplier<@NotNull T> may lead to incorrect behavior of mentioned code inspections (it must be a bug which probably will be fixed later). Here is an example of such behavior:

Supplier<@NonNull Integer> supplier = () -> null; // no warnings
Integer result = supplier.get();
if(result != null) // warning - Condition 'result != null' is always 'true'
    result++;

Constant conditions & exceptions code inspection suggests to " Unwrap 'if' statement ", following this advice in this case will lead to NullPointerException .

To avoid such mistakes you can add the following Search Templates to Structural Search Inspection :

//Search template:
Supplier<@NotNull $T$>
//Replace template:
NotNullSupplier<$T$>
//Search template:
Function<$T$, @NotNull $R$>
//Replace template:
NotNullFunction<$T$, $R$>
//Search template:
BiFunction<$T$, $U$, @NotNull $R$>
//Replace template:
NotNullBiFunction<$T$, $U$, $R$>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM