Automatic @NotNull/@Nullable/@Contract inference in IntelliJ IDEA 14

Java annotations are awesome and helpful, but you need to add them by hand. Well, not anymore, because IntelliJ IDEA will do that for you in some quite important cases.

Jars in your dependencies are stuffed with methods and sometimes it may be difficult to tell whether you can pass null there without blowing things up, or whether you should be ready to get null as a method result.

If you’re lucky, the documentation will specify that, if not, you have to read the source code, or even the decompiled output, which is not always as easy as you’d like it to be. There are, of course, NotNull/Nullable annotations available in various frameworks, but not everybody uses them. JDK doesn’t, for example. IntelliJ IDEA supports external annotations, but they also don’t cover most of existing jars.

Well, this is what happens now. IntelliJ IDEA will look carefully at SDK and libraries bytecode and will infer these annotations automatically so that they can later be used to analyze source code to spot places where you overlooked null. You can see these inferred annotations in italic in the editor gutter.

Screenshot from 2014-09-01 17:49:04

Contrary to the already available Infer Nullity feature, this one works with bytecode and is completely automatic: the results are just there in the editor, and you don’t have to do anything to make that happen.

Of course, the logic behind this feature is not as simple as “if a parameter is immediately dereferenced, then it’s @NotNull”. There’s science at work behind the curtains that does a lot more, for example, recursively processes delegating method calls.

Screenshot from 2014-09-02 14:25:29

For methods with a more complex behavior, as you probably know, we have the method contracts. These are now inferred, too. Why is this important? Well, suppose you’re using Apache Commons StringUtils and have such warnings in your code:

Screenshot from 2014-09-02 12:14:58

Earlier IntelliJ IDEA had no clue that code execution wouldn’t even reach the “startsWith” call if the url is null because it didn’t look inside StringUtils.isEmpty. You could of course remove those yellow warnings in extractPrefix by looking inside isEmpty yourself and adding a contract “null -> true”, but that’s so boring! That’s exactly a job for computer, not you, and now IntelliJ IDEA does it automatically, looking at byte and source code.

Screenshot from 2014-09-02 12:25:32

Get the latest preview build and see how this works for you. We are eager to hear your feedback, be it bugs, usability issues or suggestions about more annotations to infer.

This entry was posted in New Features and tagged , , , . Bookmark the permalink.

38 Responses to Automatic @NotNull/@Nullable/@Contract inference in IntelliJ IDEA 14

  1. Charles Wise says:

    How do you activate this?

  2. Madis says:

    Great work!

  3. Casper says:

    Looks great. Would it be possible to remove the org.jetbrains.annotations part from the documentation screens, though? It doesn’t really add much information (that fact that it is Nullable is enough) and clutters the documentation a bit, imo.

  4. As a funny result of this great feature IntelliJ IDEA is worried about passing null into Validate.notNull(..) method :)

  5. Bartek Andrzejczak says:

    I’m using the most recent community version build and I can’t get it to infer @Contract annotations. It’s good with nullability, but when it comes to contracts i just can’t run it. Is there some action that does it? I can’t find it in Action Finder. I can write my own @Contract and IntelliJ will tell me when method code is wrong, but I can’t make it to write it’s own contract.

    • Peter Gromov says:

      Which build exactly are you using (Help | About | Ctrl+C)? Only recent 138.* builds support that functionality. Please also note that contracts are not inferred for methods that can be overridden, i.e. non-static non-private non-final methods don’t have contracts. If all this is inapplicable, please create a YouTrack issue (https://youtrack.jetbrains.com/) with more specific description with code samples and/or screenshots attached.

  6. Ryan Gardner says:

    Are there quick fixes available for this?

    For groovy, it would be awesome to automatically have it suggest adding the Elvis operator.

    For java it’d be a bit trickier to come up with a universal quick fix, but having a couple to pick from (such as just adding a quick null check boilerplate for you to put the null handling in would be a nice quick fix)

  7. Igor Kolomiets says:

    Great work!

    There was nice podcast (in Russian) recently with Ilya Klyuchnikov on a subject of supercompilation: http://eaxcast.rpod.ru/330855.html

  8. wow ! great work, sexy stuff

  9. Peter Xanadus says:

    This feature works fine in IntelliJ IDEA 14 138.2458 but stopped working in 139.69 (for me)

  10. Jon Thomas says:

    I just upgraded from 13 to 14 and I’m now seeing lots of warnings about guava’s Preconditions.checkNotNull. The inferred contract seems correct (value = “null -> fail”, pure = true), but when I pass in an object that might be null, I get a warning “Argument ‘x’ might be null.”

    This should not produce a warning, because checkNotNull allows a null parameter.

    Is there a setting I need to turn on to get this to work correctly with IntelliJ 14?

    • Peter Gromov says:

      There’s no setting except for disabling the inspection temporarily. It’s a bug, we’ll include the fix into one of the upcoming 14.0.x EAPs.

  11. Sam says:

    It looks like the contract from StringUtils#substringBetween(String, String, String) is wrong:


    @org.jetbrains.annotations.Contract("!null,_,_->null;_,!null,_->null;_,_,!null->null;_,_,null->null;_,null,_->null;null,_,_->null")

    The first contract looks suspicious. Indeed, while in my code I have a nullable url, it tells me that the result of StringUtils.substringBetween(url, "/geocache/", "_"); is always null, which is wrong.

  12. Siilk says:

    How can I turn this feature off?

  13. Peter Gromov says:

    So far there’s no way to turn this off. But nothing is added to your code at all. It’s just an icon, like many others in IntelliJ IDEA.

    • Siilk says:

      Well, that it slightly better. But still, there should be away to turn this annoying icon off. It’s really disappointing that you are rushing to release features like that with corresponding settings not being properly implemented yet.

      • Peter Gromov says:

        Possibly. There are many features in IDEA which don’t have corresponding settings, and you don’t complain about them. So something is different about this one, and it’s hard to help you if you don’t tell what exactly is wrong. You haven’t even specified which features annoy you: the icons themselves or the underlying functionality — external annotations, annotations inferred by byte code or annotations inferred from source code. I’d suggest you to file an issue to the tracker (https://youtrack.jetbrains.com/dashboard), preferably with your reasons, and we can continue the discussion there.

Leave a Reply

Your email address will not be published. Required fields are marked *