简体   繁体   中英

Contract Checking in Maven Build

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 eg 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:

  • Download/clone Bentolor's CLI inspector tool into your working directory ie the directory where the .idea folder is
  • Create an IJ inspection profile with just these inspections enabled: Constant conditions and exceptions and Contract Issues
  • Create an inspection scope if you like - this will restrict your inspections to run only on certain files
  • Edit that .ideainspect file that comes with Bentolor's tool, setting your inspection profile & scope that you've just defined, or use project defaults if you haven't defined any
  • Also in the .ideainspect file, set the ideahome property to the path where you've insalled IJ eg ideahome= C:\\Program Files (x86)\\JetBrains\\IntelliJ IDEA Community Edition 15.0.6
  • Finally, to include this in the Maven build, add the following to your POM.xml:
<plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.6.1</version>
    <executions>
      <execution>
        <phase>verify</phase>
        <goals>
          <goal>execute</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <properties>
      </properties>
      <scripts>
        <script>file:///${project.basedir}/idea-cli-inspector/ideainspectMvn.groovy</script>
      </scripts>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <!-- any version of Groovy \>= 1.5.0 should work here -->
        <version>2.5.0</version>
        <type>pom</type>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>commons-cli</groupId>
        <artifactId>commons-cli</artifactId>
        <version>1.2</version>
      </dependency>
    </dependencies>
  </plugin>

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:

task inspect(type:Exec) {
  workingDir '/idea-cli-inspector'

  //on windows:
  commandLine 'cmd', '/c', 'groovy ideainspect.groovy'
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM