Proper checker framework config for maven

867 Views Asked by At

I would like to know the proper way for using checker framework with java 17. I have looked through docs and ended up here: https://github.com/typetools/checker-framework/blob/master/docs/examples/MavenExample/pom.xml

But it does not seem to work. Here is my pom:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>learn</artifactId>
        <groupId>tutorial</groupId>
        <version>1.0.0-Final</version>
    </parent>

    <artifactId>checkerframework</artifactId>
    <name>checkerframework</name>
    <packaging>jar</packaging>

    <properties>
        <checkerframework.version>3.22.1</checkerframework.version>
    </properties>
    
    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.checkerframework/checker -->
        <dependency>
            <groupId>org.checkerframework</groupId>
            <artifactId>checker</artifactId>
            <version>${checkerframework.version}</version>
            <scope>compile</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.checkerframework/checker-qual -->
        <dependency>
            <groupId>org.checkerframework</groupId>
            <artifactId>checker-qual</artifactId>
            <version>${checkerframework.version}</version>
            <scope>compile</scope>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>

                <configuration>

                    <!-- Must fork or else JVM arguments are ignored. -->
                    <fork>true</fork>
                    <release>17</release>

                    <compilerArgs combine.children="append">
                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
                    </compilerArgs>

                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

I have omitted profiles for other JDKs. However when I click run button in IntelliJ, it does not throw warnings. Or it does not even shows yellow underlines saying check framework has found this issue or something like that.

What am I missing here?

I have used lombok previously and it wasn't a hassle. Just add the dependency and IJ will take care of processing.

SO how can I achieve that here? I saw modifying IJ's annotation settings but I thought that was an overkill especially I want this to be cross platform. So I look for purely based script.

Here is my Main class I used to check:

public class Main {

    public static @Positive int positiveInteger;

    public static void main(final String[] args) {

        positiveInteger = -4;

        System.out.println(positiveInteger);
        // should show warning underline  or something on positiveInteger ???
    }
}

I have also tried adding all annotation processors as show here (https://www.baeldung.com/checker-framework) but that too failed:

1

There are 1 best solutions below

1
Laonel On

You have to add checker framework's annotation processors that you want to use. Additionally, to make it work with JDK16+ you have to include some add-opens to JDK arguments.

If you are also using Lombok the maven compiler plugin configuration might look something like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <fork>true</fork> <!-- Must fork or else JVM arguments are ignored. -->
        <compilerArgument>-Xlint:all</compilerArgument>
        <showDeprecation>true</showDeprecation>
        <showWarnings>true</showWarnings>
        <annotationProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </path>
            <path>
                <groupId>org.checkerframework</groupId>
                <artifactId>checker</artifactId>
                <version>${checker-framework.version}</version>
            </path>
        </annotationProcessorPaths>
        <annotationProcessors>
            <annotationProcessor>
                lombok.launch.AnnotationProcessorHider$AnnotationProcessor
            </annotationProcessor>
            <annotationProcessor>
                org.checkerframework.checker.nullness.NullnessChecker
            </annotationProcessor>
        </annotationProcessors>
        <compilerArgs combine.children="append">
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
        </compilerArgs>
    </configuration>
</plugin>

Then the selected checkers (NullnessChecker in this example) will be used when running mvn compile. Add an annotationProcessor element for each checker that you want to use. You can find all the checkers that the Checker Framework has in the manual (https://checkerframework.org/manual).

In the example you linked checkers configuration is defined under thecheckerframework profile.