IntelliJ IDEA 2018.2 EAP3: advanced @Contract annotations and more
We’ve just finished assembling a new EAP build of IntelliJ IDEA 2018.2. You’re very welcome to download it right now!
IntelliJ IDEA supports the @org.jetbrains.annotations.Contract annotation, which allows you to specify a method reaction when a particular parameter is passed. This can help with nullability analysis and some other inspections.
Suppose you have a utility method:
Then the following method does not issue a warning on string dereference:
The contract says that if
isNotEmptyString returns false. Therefore,
str.charAt(0) is not executed.
In the upcoming IntelliJ IDEA 2018.2, we’re improving the Contract language to support more return values. New values include
_ -> this means that the non-static method always returns the
this object (like
A contract like
_ -> param1 means that the method always returns its first parameter (unless it throws an exception).
If a contract returns a
new value, it means that the method always returns a newly allocated object. New values allow you to describe the method behavior more precisely. Imagine a coalesce method:
Its contract can be described as
null, _ -> param2; !null, _ -> param1. This reads as “if the first parameter is
parameter#2 is returned; if the first parameter is not
parameter#1 is returned”.
It’s not always necessary to specify the contract. Sometimes (for example, in the “coalesce” example above) it can be inferred automatically for static, private, or final methods.
The contract information is available for various inspections and actions which can use it to produce better warnings or remove false-positives. For example, in the upcoming IntelliJ IDEA 2018.2, you may get a warning in the code like
stringBuilder = stringBuilder.append(something); because now the IDE knows that the append method will return its qualifier, so there’s no reason to reassign the
Similarly, the inspection Result of method call ignored will not show a warning if a pure method is known to always return its argument. Likely it’s a validation method which either throws or returns an argument for convenience, so using a return value is unnecessary.
As a result, several new kinds of bugs can now be detected. For example, if you use the coalesce method described above, the IDE is now aware that the inner condition is always false in the following code:
Actions like Analyze dataflow from here are also aware of new contracts now. For example, consider the following class:
When starting dataflow analysis from the constructor parameter, you can now eventually reach the getter, as analysis knows that
Objects.requireNonNull returns its argument unless it fails (its contract is
"null -> fail; _ -> param1"):
Speaking of our annotations, IntelliJ IDEA now provides annotations.jar as a Maven repository library. Previously, for a project that didn’t use Maven or Gradle, IntelliJ IDEA would suggest adding annotations.jar (or junit.jar) from its own installation directory.
Now, when there are some unresolved references to annotations like @NotNull or @Contract, IntelliJ IDEA will provide a quick-fix to add annotations.jar from the Maven repository. After you download this JAR for the first time, it will be stored in the local .m2/repository.
Several libraries can now be added to a project as Maven repository libraries: JUnit 3 and JUnit4, Testng, JCIP, and our own annotations library.
Jump outside closing bracket/quote with Tab
In the upcoming IntelliJ IDEA 2018.2, you will be able to navigate outside the closing brackets, or closing quotes, by pressing Tab. To customize this behavior of Tab, go to Preferences | Editor | General | Smart keys and select Jump outside closing brackets/quote with Tab. This will work in Java, Kotlin, Groovy, SQL, and Python files.
Last week we introduced breakpoint intentions, which are available via Alt+Enter. This latest build further enhances this functionality: please welcome new breakpoint intentions that allow filtering by a caller method.
Sometimes it is important to stop at a breakpoint only when a certain condition applies to the call stack. Now, if you filter a breakpoint hit by the caller method, it will stop at a breakpoint only if it’s called from the specified method. (Or, vice versa, it will not stop at a breakpoint if it’s called from that method.)
You can also set a caller method filter by using the Caller filters field in the Breakpoint dialog.
In other news, we’ve improved our support for SVG files so that now the IDE provides completion in them. Under the hood, it reuses the SVG part of RelaxNG schema from HTML5 support. Quick Documentation Lookup is also available for SVG files now.
Version Control System
We’ve also improved our Git integration with a small yet very useful feature: the IDE now autocompletes tags in the Checkout dialog.
We’d love to hear your feedback on these cool new features! Please share your thoughts with us in the discussion forum or on Twitter. If you stumble on a bug, please report it to our issue tracker. Thanks!