Improved Data Flow Analysis in IntelliJ IDEA 2018.2

IntelliJ IDEA gives warnings in the editor if it detects suspicious code based on an analysis of data flow. In IntelliJ IDEA 2018.2 we can now see information known about a particular symbol. For example, if a number of instanceof checks have been performed against a parameter, pressing Ctrl+Shift+P twice shows us which types this value may be:

If we do this with an Optional value, we can see the value is known to be present if, for example, an ifPresent() check has already been done:

This analysis can show really useful information about known values, as you can see from this example with an int value:

Data flow analysis is smarter with array values. IntelliJ IDEA can now show the possible values from an array if the array was statically initialized. For example, if we have an array containing the number of days in each of the months of the year, and some logic to validate whether a given date value is valid, we can see which values are possible at each stage of the validation:

IntelliJ IDEA 2018.2 also knows if a collection was initialized as an empty collection, and can highlight errors caused by accessing elements that don’t exist:

Data flow analysis also supports more math operations than before, like division and right-shift.

IntelliJ IDEA 2018.2 can work out if a method returns an immutable value, or an immutable view of a value. So if, for example, a method returns a list wrapped in Collections.unmodifiableList(), the gutter annotation icon will show that this method has an inferred annotation of @UnmodifiableView, since unmodifiableList returns a view onto a list that cannot be altered.

This means that if a modifying method is called on the result of this method, IntelliJ IDEA can warn us that this is probably incorrect:

Also new is the ability to look inside streams created using Stream.of() to work out if downstream operations are logical. If, for example, we create a Stream of Optional values where all the values are known to be present, IntelliJ IDEA will point out that a call to check to see if isPresent is true on all the Optional values will always be true, and can therefore be simplified.

Because of this increased intelligence, there will also be no warning that the call to get needs a preceding call to isPresent. Note that this feature only works for up to three values inside the Stream.of call.

Smarter warnings are also available for Hamcrest matchers, so when using Hamcrest inside tests we’ll see fewer instances of warnings, for example when calling get on Optional. Similarly we’ll also see fewer incorrect “may produce NullPointerException” warnings on Nullable values.

Data flow analysis now supports checks using isAssignableFrom and isInstance, so we see fewer false positives and more useful warnings:

Finally on this topic, IntelliJ IDEA 2018.2 has increased support for constant evaluation of simple methods, meaning that if certain Math or String methods are called with constant values, IntelliJ IDEA can warn us that certain conditions will always or never be true: