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.
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.
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:
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.
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.
Charles Wise says:
October 2, 2014How do you activate this?
Peter Gromov says:
October 2, 2014You don’t have to do anything special, it’s active already.
Rama Patria Himawan says:
July 18, 2016I accidentally removed it from my intellij, do you know how can I turn it on again?
Peter Gromov says:
July 18, 2016What “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”.
Madis says:
October 2, 2014Great work!
Casper says:
October 3, 2014Looks 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.
Peter Gromov says:
October 3, 2014Thanks for the suggestion, we’ll think how to do it: https://youtrack.jetbrains.com/issue/IDEA-130773
Artem Khvastunov says:
October 3, 2014As a funny result of this great feature IntelliJ IDEA is worried about passing null into Validate.notNull(..) method 🙂
Peter Gromov says:
October 3, 2014Are you using the public preview build? Could you please tell us the qualified name of that Validate class?
Artem Khvastunov says:
October 3, 2014Yes 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, 2014I’ve told about IU-138.2210. IU-138.2458 works fine. Good job!
Bartek Andrzejczak says:
October 3, 2014I’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, 2014Which 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.
Ryan Gardner says:
October 3, 2014Are 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, 2014Yes, there are quick fixes in Java. As for Groovy, you can vote/watch IDEA-48786
Igor Kolomiets says:
October 3, 2014Great work!
There was nice podcast (in Russian) recently with Ilya Klyuchnikov on a subject of supercompilation: http://eaxcast.rpod.ru/330855.html
Asraful Chowdhury says:
October 12, 2014wow ! great work, sexy stuff
Peter Xanadus says:
October 16, 2014This feature works fine in IntelliJ IDEA 14 138.2458 but stopped working in 139.69 (for me)
Peter Gromov says:
October 16, 2014We’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, 2014is there a chance that it’ll come back in a later EAP or the release version?
Peter Gromov says:
October 17, 2014For nullable annotations, it’s not very likely. However, you can still enable this analysis in your IDEA by following the instructions at https://youtrack.jetbrains.com/issue/IDEA-130063#comment=27-812471
Jon Thomas says:
November 18, 2014I 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, 2014There’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.
Sam says:
November 22, 2014It 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.Peter Gromov says:
November 25, 2014Thanks for filing it as https://youtrack.jetbrains.com/issue/IDEA-133367
Siilk says:
January 12, 2015How can I turn this feature off?
Andrey Cheptsov says:
January 13, 2015I believe by disabling the corresponding inspection: https://www.dropbox.com/s/mtaub8rq8jm3y54/Screen%20Shot%202015-01-13%20at%2014.04.14.png?dl=0
Siilk says:
January 13, 2015I am not talking about inspections/warnings, but about the automatic annotation insertion, this: http://i369.photobucket.com/albums/oo135/Siilk_/42_zps87109e01.png
Peter Gromov says:
January 13, 2015Why do you want to do this?
Siilk says:
January 13, 2015Because I want to switch this annoying feature off, isn’t that obvious?
Peter Gromov says:
January 14, 2015That 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, 2015I 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, 2015It’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.
Peter Gromov says:
January 15, 2015So 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, 2015Well, 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, 2015Possibly. 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, 2015Lodged IDEA-135399
Erik Visser says:
April 17, 2015Thx for adding this ticket. This seems like the proper place to discuss this.
I’ll second this request.
Thomas says:
February 2, 2017I’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, 2017Thomas, 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.
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 […]