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

Posted on by Peter Gromov

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.

Comments below can no longer be edited.

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

  1. Charles Wise says:

    October 2, 2014

    How do you activate this?

    • Peter Gromov says:

      October 2, 2014

      You don’t have to do anything special, it’s active already.

      • Rama Patria Himawan says:

        July 18, 2016

        I accidentally removed it from my intellij, do you know how can I turn it on again?

        • Peter Gromov says:

          July 18, 2016

          What “it”? If you removed the gutter icon, you can press Alt+Enter when editor caret is on the method declaration, and choose “Show Annotations Inferred from Source Code”.

  2. Madis says:

    October 2, 2014

    Great work!

  3. Casper says:

    October 3, 2014

    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. Artem Khvastunov says:

    October 3, 2014

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

    • Peter Gromov says:

      October 3, 2014

      Are you using the public preview build? Could you please tell us the qualified name of that Validate class?

      • Artem Khvastunov says:

        October 3, 2014

        Yes I am. But currently I cannot reproduce it. I’ll check it again on Monday when I’m at work.

      • Artem Khvastunov says:

        October 6, 2014

        I’ve told about IU-138.2210. IU-138.2458 works fine. Good job!

  5. Bartek Andrzejczak says:

    October 3, 2014

    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:

      October 3, 2014

      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:

    October 3, 2014

    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)

    • Peter Gromov says:

      October 3, 2014

      Yes, there are quick fixes in Java. As for Groovy, you can vote/watch IDEA-48786

  7. Igor Kolomiets says:

    October 3, 2014

    Great work!

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

  8. Asraful Chowdhury says:

    October 12, 2014

    wow ! great work, sexy stuff

  9. Peter Xanadus says:

    October 16, 2014

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

    • Peter Gromov says:

      October 16, 2014

      We’ve turned off automatic @Nullable inference on methods as it produces too many false positives. Other annotations should be inferred as previously. If you observe anything unexpected, please report to YouTrack: https://youtrack.jetbrains.com/newissue

      • Peter Xanadus says:

        October 16, 2014

        is there a chance that it’ll come back in a later EAP or the release version?

  10. Jon Thomas says:

    November 18, 2014

    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:

      November 25, 2014

      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:

    November 22, 2014

    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:

    January 12, 2015

    How can I turn this feature off?

    • Andrey Cheptsov says:

      January 13, 2015

      I believe by disabling the corresponding inspection: https://www.dropbox.com/s/mtaub8rq8jm3y54/Screen%20Shot%202015-01-13%20at%2014.04.14.png?dl=0

    • Peter Gromov says:

      January 13, 2015

      Why do you want to do this?

      • Siilk says:

        January 13, 2015

        Because I want to switch this annoying feature off, isn’t that obvious?

        • Peter Gromov says:

          January 14, 2015

          That is obvious, of course. But why is it annoying you, this isn’t obvious. Your explanation might help making it less annoying.

          • Siilk says:

            January 14, 2015

            I don’t want annotations to be added to my code automatically without any control whatsoever. So, again, how can I turn this off?

    • Stefanos says:

      February 25, 2015

      It’s not adding them to your code ffs.

      It’s infering them from the source/byte code analysis and showing you the result.

      What it really is: an indication of how your code behaves.
      You can use this. Read what the IDE has infered, and see if it’s what you intended to do.

  13. Peter Gromov says:

    January 15, 2015

    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:

      January 15, 2015

      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:

        January 19, 2015

        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.

        • Siilk says:

          January 20, 2015

          Lodged IDEA-135399

          • Erik Visser says:

            April 17, 2015

            Thx for adding this ticket. This seems like the proper place to discuss this.

            I’ll second this request.

  14. Thomas says:

    February 2, 2017

    I’m using Android Studio 2.3 which is based off IntelliJ IDEA 162.2228.14.

    I have a Precondition class that has a basic fluent syntax, like

    Precondition.check(something).isNotNull()

    The only method @Contract I could think of adding to my isNotNull() implementation here is @Contract("->fail") but this is certainly stupid, because IntelliJ does not know at which variable this is directed. Is there any way to specify the contract or otherwise make modern IntelliJ be aware of the “null” check so it automatically suppressed the null warning?

    • Peter Gromov says:

      February 2, 2017

      Thomas, contracts are currently not expressive enough to handle such cases, and I have no idea how they can be improved in this respect. If it’s some common library, we can hardcode such usage pattern in IDEA, otherwise I’m afraid I know of no strategy to deal with this.

  15. IntelliJ IDEA 2018.2 EAP3: advanced @Contract annotations and more | IntelliJ IDEA Blog says:

    May 29, 2018

    […] introduced the @Contract annotation a while ago, and we’ve been improving it ever since. We added automatic inference, and today we are ready to take it even […]

Subscribe

Subscribe for updates