Better Control Flow Analysis with Contract Annotations and IntelliJ IDEA 13

As we’re closing in on the release date, we’re going to publish more details on the new features of IntelliJ IDEA 13. Today we’d like to tell you about the new @Contract annotation.

If you are aware of @Nullable/@NotNull annotations, you probably know how helpful they are against NullPointerException. The new @Contract annotation brings one more layer of safety for your code by defining dependencies between method arguments and return values. This information lets IntelliJ IDEA provide smarter control flow analysis for your code and avoid probable errors.

Here’s an example: say we’ve got a method sort() that returns a sorted list or a null value if the argument is null.

Now if we try to to call this method with a null value and check the result against null, IntelliJ IDEA will not complain because it doesn’t know that a null input yields a null output.

How can we help IntelliJ IDEA? That’s right… Decorate the sort() method with a @Contract annotation, specifying that null inputs yield null outputs:

Now IntelliJ IDEA can see that the sort() method always returns null and the if statement is redundant. The corresponding message appears in the editor.

The @Contract annotation value has the following syntax:

  • contract ::= (clause ‘;’)* clause
  • clause ::= args ‘->’ effect
  • args ::= ((arg ‘,’)* arg )?
  • arg ::= value-constraint
  • value-constraint ::= ‘any’ | ‘null’ | ‘!null’ | ‘false’ | ‘true’
  • effect ::= value-constraint | ‘fail’

The constraints denote the following:

  • _ – any value
  • null – null value
  • !null – a value statically proved to be not-null
  • true – true boolean value
  • false – false boolean value
  • fail – the method throws exception, if the arguments satisfy argument constraints

The @Contract annotation is a powerful and flexible tool that helps make your APIs safer. However, you can use it not only for annotating your own code but also for other existing libraries.

Once you’ve configured the annotations for the project libraries, the IDE stores this information in simple XML files so it can be shared with the team via version control.

To enable the annotations in your project, just add <IntelliJ IDEA Home>/lib/annotations.jar to the classpath via Project Structure.

UPDATE: Please find the latest annotations.jar in Maven repository.

Develop with Pleasure!

Comments below can no longer be edited.

32 Responses to Better Control Flow Analysis with Contract Annotations and IntelliJ IDEA 13

  1. Avatar

    Vaclav says:

    October 21, 2013

    I really love checking for nullity in IDEA.

    What I miss however is an option to consider everything @NotNull in your project code unless otherwise stated.

    Basically make it behave like types without question mark in Kotlin. And make @Nullable replacement for the Kotlin question mark. So the code is not so polluted by @NotNull.

    • Avatar

      Peter says:

      October 22, 2013

      FindBugs/JSR305 has the ParametersAreNonnullByDefault annotation, and the option to add your own. I would love it if IntelliJ would support this too.

      The contract annotation looks pretty readable, but will IntelliJ mark any spelling or syntax errors?

      • Avatar

        Tom says:

        October 26, 2013

        I’m also waiting for support all of the JSR305 annotations. Especially the @ParametersAreNonnullByDefault. Are there any plans to implement this functionality?

        • Avatar

          gromopetr says:

          October 30, 2013

          There’s a request for that which you can watch/vote for: http://youtrack.jetbrains.com/issue/IDEA-65566
          We’re planning to implement this, but not yet sure how exactly, so probably not in version 13.0.

  2. Avatar

    Josh says:

    October 21, 2013

    “As we’re closing on to the release date” – Is there an expected release date for 13 yet? I’ve held off from using the EAP’s this time so looking forward to the release!

    • Avatar

      Andrey Cheptsov says:

      October 21, 2013

      The release is coming in early December.

  3. Avatar

    Jacky Chan says:

    October 21, 2013

    Could you upload the annotations jar (13.0) to the central Maven repository to http://central.maven.org/maven2/com/intellij/annotations/ ?

  4. Avatar

    Gerard Krupa says:

    October 21, 2013

    Will this annotations library be available as a Maven dependency in Central?

  5. Avatar

    James says:

    November 5, 2013

    Is the @Contract annotation why http://youtrack.jetbrains.com/issue/IDEA-35808 was removed from 13? I’d love to see a quick blog post explaining how to teach IntelliJ about contracts for third party jars.

  6. Avatar

    Alexander Kosenkov says:

    December 3, 2013

    Andrey, there’s a problem with screen shot on the front page on http://www.jetbrains.com/idea/whatsnew/
    (CONTRACT ANNOTATION http://www.jetbrains.com/idea/whatsnew/img/13/ij13_contract.png)

    List copy = new ArrayList(…)
    copy can never be null, but @Contract annotaion states otherwise (null -> null).

  7. Avatar

    Andrey Haliullin says:

    December 4, 2013

    As far as I can see, 13 version of com.intellij.annotations still not available in maven central repo, while new Idea is already released. I like the feature you described very much, so when you are going to deploy this jar to maven?

    Thank you!

    • Avatar

      Peter Gromov says:

      December 15, 2013

      Andrey, to be notified on annotations.jar status in Maven Central please watch http://youtrack.jetbrains.com/issue/IDEA-117520

    • Avatar

      kristian rosenvold says:

      December 18, 2013

      The groupid changed; org.jetbrains.annotations

  8. Avatar

    James says:

    December 6, 2013

    Can @Contract be added to an @Override method if the super-type does not have an @Contract annotation? If the super-type does have @Contract, how does this affect the @Override method? Thanks!

    • Avatar

      Peter Gromov says:

      December 15, 2013

      Yes, @Contract can be added to an overriding method. Contract annotation on the super method has no effect currently on the overriding method, we haven’t yet decided what’s the best way to handle this.

      • Avatar

        James says:

        December 19, 2013

        Okay, thank you. Personally, I believe that is adequate if contradicting / missing @Contracts are reported by an inspection similar to “@Nullable Problems.”

  9. Avatar

    Philipp Middendorf says:

    December 18, 2013

    A little correction to your grammar: You wrote:

    value-constraint ::= ‘any’ | ‘null’ | ‘!null’ | ‘false’ | ‘true’

    This should be ‘_’ instead of ‘any’. I stumbled on that. Example:

    @Contract("null,_,_ -> fail")
    public void foo(Object nullable,Object bar,Object baz) {
    if(nullable == null)
    throw new RuntimeException("nullable is null!");

    PS: As of the 17th of December, the IntelliJ contract annotations are finally in Maven Central!

  10. Avatar

    Imran Zahid says:

    December 28, 2013

    Can @Contracts be added to method arguments?
    I am trying to override Google Guavas @Nullable. My annotation.xml file is:

    Now in my code I have done:

    return Maps.uniqueIndex(entities, new Function() {
    @Override @Nonnull
    public Long apply(@Nonnull E input) {
    return input.getId();

    However IDEA is complaining that @Nonnull E input must not override @Nullable parameter

    • Avatar

      Peter Gromov says:

      January 3, 2014

      No, @Contract annotations cannot be added to method parameters yet. Do you have any suggestions what they could do and how they would look?

      Overriding @Nullable parameter with @Nonnull is reported because it may lead to issues when some other passes null to your function because the super signature contains @Nullable.

      • Avatar

        Imran Zahid says:

        January 3, 2014

        Mu annotations.xml (created by IDEA) is:

        This implied that @Contract could be added to method parameters, but if you say no, then I think this is a bug, as IDEA lets me add a method parameter contract (but doesn’t work).

        The reason I wanted a method parameter @Contract is in my Maps.uniqueIndex example where I am sure my application would never pass null values, thus wanted to override the libraries @Nullable method parameters.

        • Avatar

          Peter Gromov says:

          January 3, 2014

          Sorry, I can’t see your annotations.xml. You can email it to me, peter@jetbrains.com.

          You can add an explicit assertion for that parameter or use Preconditions#checkNotNull(T) (externally annotated with a contract). Or suppress the inspection for that particular place. Or just remove @Nullable annotation from Function.apply. It’s too generic a method to proclaim anything about it.

  11. Avatar

    Richard Kent says:

    December 31, 2013

    Please bring back the Configure IsNull/IsNotNull/True/False Check/Assert Methods functionality from Idea 12 (as an aside, a loss of important functionality on upgrade is never acceptable). The Contract annotation is certainly more expressive but simply doesn’t work well in a mixed environment where some devs are using Idea and some are on eclipse. If you are not willing to resurrect the old “methods” functionality then please allow the contract definitions to be stored in the Idea project files, and not in annotations in the source files.

  12. Avatar

    Pat says:

    March 19, 2014

    RE: UPDATE: Please find the latest annotations.jar in Maven repository.

    So, should we be adding the following dependency to our project’s pom.xml?


    If so, what about Project Structure -> Platform Settings -> SDKs -> Annotations?

    Should we remove the entry /IntelliJ IDEA 13.1/lib/Annotations.jar?

    If not, should we simply overwrite /IntelliJ IDEA 13.1/lib/Annotations.jar with the new JAR file?

  13. Avatar

    Yuriy says:

    May 23, 2014

    Nullity inference does not work if method has contract “null -> fail”, but it works in Idea 12 with configured Assert/Check methods (((.

    public class Test {
    public static void main(String[] args) {
    String x = null;

    public static void test(String x) {
    if (x == null) {

    // some method that throws exception if x == null
    // annotated with @Contract(“null -> fail”)

    // idea highlights possible null pointer exception here

    • Avatar

      Peter Gromov says:

      May 26, 2014

      Is it really possible NPE highlighted or “result of toUpperCase is ignored”? Which IDEA version are you using? I’ve added this method to your code and it works fine for me:

      @Contract(“null -> fail”)
      private static void checkNotNull(final String x) {
      if (x == null) {
      throw new RuntimeException();

  14. Avatar

    PeJoBo says:

    August 27, 2014

    I’m struggling with fest assertion “assertThat(x).isNotNull()” and “assertThat(x).isNull()” (e.g. for org.fest.assertions.Assertions org.fest.assertions.StringAssert). As far as I see with @Contract it will not be possible to support both methods. And I’m still struggling with the first method, but that seems to be a technical problem. @Contract(“null -> fail”) does not prove my parameter to be not null in the following code.

    • Avatar

      PeJoBo says:

      August 27, 2014

      IntelliJ 13.1.4

    • Avatar

      Peter Gromov says:

      September 1, 2014

      Please file a YouTrack (http://youtrack.jetbrains.com/dashboard#newissue=yes) issue and attach a self-contained code sample there that you wish to be working. Please also specify which library with assertThat method you’re using.

Discover more