Updated Inspections and Intentions in IntelliJ IDEA 2018.2

Posted on by

We’ve talked about a lot of the changes in IntelliJ IDEA 2018.2 here in the blog, such as the improved data flow analysis and advanced contract annotations. In this post we’re going to look at pretty much all the other updates to inspections and intentions.

IntelliJ IDEA 2018.2 can suggest adding an Exception to an existing catch block via Java 7’s multi-catch:

There are a number of changes to inspections that apply to loops and Collections. For example, if we have code that removes items from a list, this is detected and can be replaced with clear() :

And if we are using remove inside a loop in a suspicious way, IntelliJ IDEA detects this and warns us. This code could be a bug, as we’re modifying the collection as we iterate over it, and this will cause us to skip elements as we iterate. This might be intentional but if it is not, the inspection will draw our attention to it so we can fix it.

In IntelliJ IDEA 2017.3 the “Unroll loop” intention was introduced, making it possible to replace loops with each call specifically. This has been expanded in 2018.2 to support loops that count down too. This functionality can be useful for looping over a small number of items as it can help readability. It may be particularly helpful in test code.

There have been a number of inspections to help migrate code both to and from using the Java 8 Streams API for a while now, along with other additions to the Collections API that came into Java 8. IntelliJ IDEA 2018.2 now supports the ability to convert Map.forEach() methods to a for loop that iterates over Map.entrySet() .

The IDE is also smarter at figuring out simplifications and improvements for if statements and boolean expressions. If, for example, we have a number of conditional branches that all contain the same expression, extracting an if condition or breaking one of the statements into two if statements will result in the duplicate code being placed in a higher-level if:

IntelliJ IDEA 2018.2 is also better at figuring out simplifications and improvements for if statements and boolean expressions, so you may see additional simplifications suggested in this type of code.

Using this technique to remove if statements may expose further simplifications that can be applied.

IntelliJ IDEA 2018.2 has added more intelligence around use of primitives and their wrappers. So if the code is using compareTo() to compare two primitives, the compareTo call will be shown in grey and pressing Alt + Enter will give the option to remove it. This works for Byte, Character, Integer, Long and Short.

The IDE can also detect places where a wrapper type (like Integer, Long) is being used when it could be a primitive type. Pressing Alt + Enter will give the option of converting this into the primitive type.

Another place where IntelliJ IDEA will suggest changing the type is if a variable can be declared as a more specific type in order to remove the need to cast.

IntelliJ IDEA now may also suggest changing the type of a field when passing the field into a method on another class that requires a different type. Previously the suggestions were around changing the target method rather than the field or variable being passed.

IntelliJ IDEA can use its knowledge of types to point out possible bugs. For example, when calling getClass on a variable that already represents a class is likely to be a mistake. Two possible fixes are offered: either to replace the call with the more explicit Class.class method (which is what the call was originally doing), or to remove the getClass() call altogether, which is likely the original intention of the code.

IntelliJ IDEA 2018.2 has a new intention for annotations which lets us wrap an unknown reference in quote to turn it into a String value.

New in IntelliJ IDEA 2018.2, the editor will grey out places where generic parameters have been declared for a method that isn’t generic, and these can be removed via Alt + Enter.

There’s also a quick fix to create a type parameter if a class uses a generic type that hasn’t been declared yet

As well as all of the above, there’s a variety of miscellaneous other new and updated inspections, intentions and quick fixes.

A new quick fix has been added to the “Implicit usage of platform’s default charset” to add StandardCharsets.UTF_8 to the offending method. It’s usually better to specify some Charset than use the default, but as usual we should check what’s the correct thing to do in our specific case.

There’s a new intention that applies to the “return” keyword that lets us introduce a local variable if the code after the return word is an expression, this can sometimes make the code easier to understand if the expressions are complex.

The “Null value for Optional type” inspection that was added in 2017.2 has been updated so it’s possible to check for places in the code that compare an Optional with null. This could either point to an unnecessary null check (since Optional values should never be null but could be empty) or could be an error that crept in when pre-Java-8 code was updated to make use of the new Optional type.

This check can be turned off via the tick box in the “Null value for Optional type” inspection setting.

The “StringBuilder can be replaced with String” inspection has been updated to also check for usages of StringJoiner with an empty delimiter that could be replaced with a String.

Other additions include:

Support for Checker Framework annotations.

Ability to mute the “Access can be private” inspection on fields with the @Inject annotation.

So check out IntelliJ IDEA 2018.2, there’s lots more intelligence there to help track down potential bugs and simplify code.