diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6e7c734bfdae..86a39f264004 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -106,3 +106,18 @@ jobs: - name: 'Test' run: | ./gradlew --no-parallel --no-daemon testSlow + + linux-checkerframework: + name: 'CheckerFramework (JDK 11)' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 50 + - name: 'Set up JDK 11' + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: 'Run CheckerFramework' + run: | + ./gradlew --no-parallel --no-daemon -PenableCheckerframework classes diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index ed4e16d52d4e..620d96f2f23f 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -46,6 +46,7 @@ dependencies { // In other words, marking dependency as "runtime" would avoid accidental // dependency on it during compilation apiv("com.beust:jcommander") + apiv("org.checkerframework:checker-qual", "checkerframework") apiv("com.datastax.cassandra:cassandra-driver-core") apiv("com.esri.geometry:esri-geometry-api") apiv("com.fasterxml.jackson.core:jackson-annotations", "jackson") diff --git a/build.gradle.kts b/build.gradle.kts index af8e0ab45ee2..adb7446901ce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ plugins { // Verification checkstyle calcite.buildext + id("org.checkerframework") apply false id("com.github.autostyle") id("org.nosphere.apache.rat") id("com.github.spotbugs") @@ -63,6 +64,7 @@ val enableSpotBugs = props.bool("spotbugs") val skipCheckstyle by props() val skipAutostyle by props() val skipJavadoc by props() +val enableCheckerframework by props() val enableMavenLocal by props() val enableGradleMetadata by props() // Inherited from stage-vote-release-plugin: skipSign, useGpgCmd @@ -495,6 +497,30 @@ allprojects { signaturesFiles = files("$rootDir/src/main/config/forbidden-apis/signatures.txt") } + if (enableCheckerframework) { + apply(plugin = "org.checkerframework") + dependencies { + "checkerFramework"("org.checkerframework:checker:${"checkerframework".v}") + // CheckerFramework annotations might be used in the code as follows: + // dependencies { + // "compileOnly"("org.checkerframework:checker-qual") + // "testCompileOnly"("org.checkerframework:checker-qual") + // } + if (JavaVersion.current() == JavaVersion.VERSION_1_8) { + // only needed for JDK 8 + "checkerFrameworkAnnotatedJDK"("org.checkerframework:jdk8") + } + } + configure { + applyToSubprojects = false + skipVersionCheck = true + // See https://checkerframework.org/manual/#introduction + checkers.add("org.checkerframework.checker.nullness.NullnessChecker") + checkers.add("org.checkerframework.checker.optional.OptionalChecker") + checkers.add("org.checkerframework.checker.regex.RegexChecker") + } + } + tasks { configureEach { manifest { diff --git a/gradle.properties b/gradle.properties index ea5b9aa9505a..f17f4f669e71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,6 +38,7 @@ calcite.avatica.version=1.16.0 # publishGradleMetadata=true # Plugins +org.checkerframework.version=0.4.14 com.github.autostyle.version=3.0 com.github.johnrengelman.shadow.version=5.1.0 com.github.spotbugs.version=2.0.0 @@ -68,6 +69,7 @@ bouncycastle.version=1.60 cassandra-all.version=3.11.2 cassandra-driver-core.version=3.6.0 cassandra-unit.version=3.5.0.1 +checkerframework.version=3.3.0 chinook-data-hsqldb.version=0.1 commons-codec.version=1.12 commons-dbcp2.version=2.6.0 diff --git a/settings.gradle.kts b/settings.gradle.kts index 4533d69ebb51..eb1147bb48f3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ pluginManagement { fun String.v() = extra["$this.version"].toString() fun PluginDependenciesSpec.idv(id: String, key: String = id) = id(id) version key.v() + idv("org.checkerframework") idv("com.github.autostyle") idv("com.github.johnrengelman.shadow") idv("com.github.spotbugs")