I'm working on a Java codebase in IJ and currently building with Maven. I would like to supplement some of the code with some form of contracts that will get picked up in the Maven build. So far, I've been unsuccessful in my search for such a capability off the shelf:
- OpenJML, but that seems to require its own tool to analyse your code and I couldn't find a way to integrate it easily into the build.
- Jetbrains Contracts. These will raise a warning in IntelliJ via an inspection, but they don't affect the build.
Note: I only care about compile-time-checkable contracts here. I have JUnit to throw at the Runtime side of things.
Contracts to Enforce:
I've added this section to answer the comment asking what kind of contracts I'd like to enforce. Ideally, I'd like the most powerful solution possible conditional on that solution being complete. When I say complete here I mean a language of contracts & a contract checker such that every statement in the language can be checked as good/bad by the checker at compile time. I'm aware this may be a big ask, but I'd be happy with even the simplest of contracts e.g. those offered by Jetbrains.
For a concrete example, consider this function:
public static Long safeToLong(String value) {
if (value == null) {
return null;
}
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return null;
}
}
This successfully passes the Jetbrains contract:
@Contract("null -> null")
And fails this contrived contract:
@Contract("null -> !null")
But with the above, contrived, bad contract, the Maven build still works just fine. The build doesn't pick up the inspection results- these are only visible from within IJ. I'd like to be able to hook into the build and fail if any contracts are violated.
Here is a solution, that works for IntelliJ Contracts. It's a bit messy, but it works:
Troubleshooting
If you get this EXCEPTION_ACCESS_VIOLATION bug while running the inspections, you may be able to fix it by adding -Dswing.noxp=true to the end of the file bin\idea64.exe.vmoptions where IJ is installed- the fix is documented at the end of this IJ crash thread.
Gradle Variant
To add this to your Gradle build it's simpler than in the Maven case. Just add this task to your build.gradle file: