Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use an EISOP CF build #155

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
73a3c08
Use EISOP CF sources (#118)
wmdietl Apr 10, 2024
644b705
Document that detail messages should not be filtered out (#146)
wmdietl Feb 6, 2024
70ca5bb
Use standard error format (#154)
wmdietl Feb 8, 2024
570d80e
Handle both `https` and `git@` clones (#158)
wmdietl Feb 8, 2024
c8d5933
Use the new `TypeInformationPresenter` to output more type informatio…
wmdietl Apr 10, 2024
11a2980
Map `type.invalid.super.wildcard` as an expected error (#166)
wmdietl Feb 27, 2024
76b33c9
Use the new `TypeUseLocation` default locations (#165)
wmdietl Apr 11, 2024
0c36cdf
Test fixes (#173)
wmdietl Apr 17, 2024
68e9072
Ensure root is set in both worlds. (#174)
wmdietl Apr 17, 2024
2d53314
Fix lower bound of type variables and unspecified subtypes. (#175)
wmdietl Apr 22, 2024
31279fb
Ensure override compatibility with type variables (#171)
wmdietl Apr 22, 2024
5462021
Stop recognizing annotations from the old package. (#181)
cpovirk Jun 30, 2024
9e4d14d
Merge.
cpovirk Jul 9, 2024
fffce55
Update to gradle 8.9 (#187)
wmdietl Jul 24, 2024
39764fb
Use `DetailedTestDiagnostic` from EISOP instead of `DetailMessage` (#…
wmdietl Jul 25, 2024
e1069a2
Introduce a `NullSpecTypeValidator` to ensure unspecified type variab…
wmdietl Jul 25, 2024
36855b8
Use EISOP release and include jspecify/jdk in jar (#188)
wmdietl Jul 25, 2024
af9dfbc
Make a local release of the reference checker (#189)
wmdietl Jul 25, 2024
a005f4e
Merge branch 'main' of github.com:/jspecify/jspecify-reference-checke…
wmdietl Jul 26, 2024
89e055f
Use same version
wmdietl Jul 26, 2024
746e34b
Build a local `eisop/checker-framework` for CI (#196)
wmdietl Jul 26, 2024
3c80e50
Report all errors as [nullness]. (#194)
cpovirk Jul 26, 2024
fc545a8
Fix capture conversion in lenient mode. (#197)
cpovirk Aug 14, 2024
eea8585
Use the new `NoContractsFromMethod` (#201)
wmdietl Aug 23, 2024
27d2334
Update to gradle 8.10 (#203)
wmdietl Aug 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ jobs:
with:
repository: jspecify/jspecify
path: jspecify
- name: Check out eisop/checker-framework
uses: actions/checkout@v4
with:
repository: eisop/checker-framework
path: checker-framework
- name: Set up Java
uses: actions/setup-java@v4
with:
Expand All @@ -27,18 +32,19 @@ jobs:
- name: Set up Gradle
uses: gradle/gradle-build-action@v3
- name: Build and Test
run: ./gradlew build conformanceTests demoTest --include-build ../jspecify
run: ./gradlew build conformanceTests demoTest --include-build ../jspecify --include-build ../checker-framework
env:
SHALLOW: 1
- name: Check out jspecify/samples-google-prototype
JSPECIFY_CONFORMANCE_TEST_MODE: details
- name: Check out jspecify/samples-google-prototype-eisop
if: always()
run: |
git fetch --depth=1 origin samples-google-prototype
git checkout samples-google-prototype
git fetch --depth=1 origin samples-google-prototype-eisop
git checkout samples-google-prototype-eisop
working-directory: jspecify
- name: Run Samples Tests
if: always()
run: ./gradlew jspecifySamplesTest --include-build ../jspecify
run: ./gradlew jspecifySamplesTest --include-build ../jspecify --include-build ../checker-framework

publish-snapshot:
name: Publish Conformance Test Framework Snapshot
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ But that's its *only* job. Notably, it is:

## Relationship to Checker Framework and EISOP

The [EISOP project](https://eisop.github.io/) maintains a fork of [Checker Framework](https://checkerframework.org/), and JSpecify conformance is one of its primary goals.
The [EISOP project](https://eisop.github.io/) maintains a fork of the [Checker Framework](https://checkerframework.org/), and JSpecify conformance is one of its goals.

This tool happens to be built on top of another fork of these ([here](https://github.com/jspecify/checker-framework)). However, please view this relationship as **implementation detail** only. Building a reference checker from scratch would simply have been too difficult, so we needed to base it on some existing tool. The choice of which tool was made purely for expediency and is **subject to change**.
This tool is built on top of the [EISOP Checker Framework](https://github.com/eisop/checker-framework). However, please view this relationship as **implementation detail** only. Building a reference checker from scratch would simply have been too difficult, so we needed to base it on some existing tool. The choice of which tool was made purely for expediency and is **subject to change**.

## Usage

Building and running this tool requires building code from several other repositories, but these instructions will take care of that automatically.
Building and running this tool depends on code from several other repositories, but these instructions will take care of that automatically.

These instructions might require workarounds or fail outright. Please file an issue if you have any trouble!

### Prework

Ideally set `JAVA_HOME` to a JDK 11 or JDK 17 installation.

Make sure you have Apache Maven installed and in your PATH, or the Gradle build will fail:
Make sure you have Apache Maven installed and in your PATH, or the `demo` script will fail:

```sh
mvn
Expand Down
157 changes: 138 additions & 19 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,25 @@ plugins {
id 'com.diffplug.spotless' version '6.25.0'
id 'io.github.gradle-nexus.publish-plugin' version '1.3.0'
id 'net.ltgt.errorprone' version '3.0.1'
// To show task list as a tree, run: ./gradlew <taskname> taskTree
id 'com.dorongold.task-tree' version '4.0.0'
}

// Nexus Publish plugin requires a group/version at the root project.
group = 'org.jspecify.reference'
version = '0.0.0-SNAPSHOT'

sourceSets {
main {
resources {
// Minimized jspecify/jdk
srcDirs += [
"${buildDir}/generated/resources"
]
}
}
}

repositories {
mavenLocal()
maven {
Expand All @@ -35,10 +48,14 @@ nexusPublishing {
}

ext {
checkerFramework = gradle.includedBuild("checker-framework")
// null if not included with `--include-build path/to/checker-framework`
checkerFramework = gradle.includedBuilds.find { it.name == 'checker-framework' }

// null if not included with `--include-build path/to/jspecify`
jspecify = gradle.includedBuilds.find { it.name == 'jspecify' }

// Location of the jspecify/jdk clone, relative to this directory
jspecifyJdkHome = '../jdk'
}

configurations {
Expand All @@ -61,8 +78,10 @@ java {
dependencies {
implementation libs.checkerFramework.checker
implementation libs.checkerFramework.checker.qual
implementation libs.checkerFramework.framework
implementation libs.checkerFramework.javacutil
// Eventually, we would want to only depend on `framework` and
// `javacutil` artifacts instead of the entire `checker`.
// implementation libs.checkerFramework.framework
// implementation libs.checkerFramework.javacutil

implementation libs.jspecify

Expand All @@ -78,8 +97,11 @@ dependencies {
errorprone libs.errorProne.core
}

// Assemble checker-framework when assembling the reference checker.
assemble.dependsOn(checkerFramework.task(":assemble"))
// If built with `--include-build path/to/checker-framework` then
// assemble checker-framework when assembling the reference checker.
if (checkerFramework != null) {
compileJava.dependsOn(checkerFramework.task(":checker:assembleForJavac"))
}

// If built with `--include-build path/to/jspecify` then
// assemble jspecify when assembling the reference checker.
Expand Down Expand Up @@ -111,6 +133,54 @@ tasks.withType(JavaCompile).configureEach {
.collect { "--add-exports=jdk.compiler/com.sun.tools.javac.$it=ALL-UNNAMED" })
}

tasks.register('includeJSpecifyJDK') {
group = 'Build'
dependsOn 'compileJava'

def srcDir = "${jspecifyJdkHome}/src"
// This directory needs to be stored at the top-level of the resulting .jar file.
// org.checkerframework.framework.stub.AnnotationFileElementTypes will then load
// the JDK classes from here instead of from checker.jar.
def dstDir = "${buildDir}/generated/resources/annotated-jdk/src/"

inputs.dir file(srcDir)
outputs.dir file(dstDir)

doLast {
FileTree srcTree = fileTree(dir: srcDir)
NavigableSet<String> specFiles = new TreeSet<>();
srcTree.visit { FileVisitDetails fvd ->
if (!fvd.file.isDirectory() && fvd.file.name.matches('.*\\.java')) {
fvd.getFile().readLines().any { line ->
if (line.contains('org.jspecify')) {
specFiles.add(fvd.file.absolutePath)
return true;
}
}
}
}
String absoluteSrcDir = file(srcDir).absolutePath
int srcPrefixSize = absoluteSrcDir.size()
copy {
from(srcDir)
into(dstDir)
for (String specFile : specFiles) {
include specFile.substring(srcPrefixSize)
}
}
javaexec {
classpath = sourceSets.main.runtimeClasspath
standardOutput = System.out
errorOutput = System.err

mainClass = 'org.checkerframework.framework.stub.JavaStubifier'
args dstDir
}
}
}

processResources.dependsOn(includeJSpecifyJDK)

tasks.withType(Test).configureEach {
if (!JavaVersion.current().java9Compatible) {
jvmArgs "-Xbootclasspath/p:${configurations.errorproneJavac.asPath}"
Expand Down Expand Up @@ -138,8 +208,10 @@ tasks.withType(Test).configureEach {

test {
include '**/NullSpecTest$Minimal.class'

inputs.files("${rootDir}/tests/minimal")

include '**/NullSpecTest$Regression.class'
inputs.files("${rootDir}/tests/regression")
}

tasks.register('jspecifySamplesTest', Test) {
Expand Down Expand Up @@ -217,24 +289,27 @@ tasks.register('demoTest', Exec) {
See https://github.com/jspecify/jspecify-reference-checker/issues/81
*/

def cfQualJar =
checkerFramework.projectDir.toPath()
.resolve("checker-qual/build/libs/checker-qual-${libs.versions.checkerFramework.get()}.jar")

if (!cfQualJar.toFile().exists()) {
mkdir(cfQualJar.parent)
exec {
executable 'jar'
args = [
'cf',
cfQualJar,
buildFile.path // Use this build script file!
]
if (checkerFramework != null) {
def cfQualJar =
checkerFramework.projectDir.toPath()
.resolve("checker-qual/build/libs/checker-qual-${libs.versions.checkerFramework.get()}.jar")

if (!cfQualJar.toFile().exists()) {
mkdir(cfQualJar.parent)
exec {
executable 'jar'
args = [
'cf',
cfQualJar,
buildFile.path // Use this build script file!
]
}
}
}

spotless {
java {
target '**/*.java'
googleJavaFormat()
formatAnnotations()
}
Expand All @@ -260,3 +335,47 @@ eclipse.classpath {
}
}
}

publishing {
publications {
jspecifyReferenceChecker(MavenPublication) {
pom {
groupId = 'org.jspecify.reference'
artifactId = 'checker'
version = project.version
name = 'JSpecify Reference Checker'
description = 'The JSpecify Reference Checker'
url = 'http://jspecify.org/'
from components.java
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
connection = 'scm:git:[email protected]:jspecify/jspecify-reference-checker.git'
developerConnection = 'scm:git:[email protected]:jspecify/jspecify-reference-checker.git'
url = 'https://github.com/jspecify/jspecify-reference-checker'
}
developers {
developer {
id = 'cpovirk'
name = 'Chris Povirk'
email = '[email protected]'
}
developer {
id = 'netdpb'
name = 'David P. Baker'
email = '[email protected]'
}
developer {
id = 'wmdietl'
name = 'Werner M. Dietl'
email = '[email protected]'
}
}
}
}
}
}
18 changes: 17 additions & 1 deletion demo
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ if [ ! -e "${jspecify}" ]; then
-DoutputDirectory="$(dirname "${jspecify}")"
fi
fi

checkerFrameworkDir="${dir}/../checker-framework/"
checkerFrameworkJar="${checkerFrameworkDir}/checker/dist/checker.jar"
if [ ! -e "${checkerFrameworkJar}" ]; then
cfVersion="3.42.0-eisop4"
checkerFrameworkJar="${dir}/build/checker-${cfVersion}-all.jar"
if [ ! -e "${checkerFrameworkJar}" ]; then
echo "Downloading $(basename "${checkerFrameworkJar}") from Maven central"
mvn -q org.apache.maven.plugins:maven-dependency-plugin:3.7.1:copy \
-Dartifact="io.github.eisop:checker:${cfVersion}:jar:all" \
-DoutputDirectory="$(dirname "${checkerFrameworkJar}")"
fi
fi

jspecify_reference_checker="${dir}/build/libs/jspecify-reference-checker-0.0.0-SNAPSHOT.jar"
if [ ! -e "${jspecify_reference_checker}" ]; then
echo "Assembling jspecify-reference-checker"
Expand All @@ -25,9 +39,11 @@ ourclasspath="${jspecify}:${jspecify_reference_checker}"

export CLASSPATH="${ourclasspath}:$CLASSPATH"

$dir/../checker-framework/checker/bin/javac \
java -jar "${checkerFrameworkJar}" \
-processorpath "${ourclasspath}" \
-processor com.google.jspecify.nullness.NullSpecChecker \
-checkerQualJar "${checkerFrameworkJar}" \
-checkerUtilJar "${checkerFrameworkJar}" \
-AcheckImpl \
-AassumePure \
-AsuppressWarnings=contracts.conditional.postcondition.false.methodref,contracts.conditional.postcondition.false.override,contracts.conditional.postcondition.true.methodref,contracts.conditional.postcondition.true.override,purity.methodref,purity.overriding,type.anno.before.decl.anno,type.anno.before.modifier \
Expand Down
17 changes: 8 additions & 9 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Development

## Codevelopment with Checker Framework fork
## Codevelopment with the EISOP Checker Framework

This project depends on
an [unreleased fork of the Checker Framework][jspecify-checker-framework].
(The [main-eisop branch] represents ongoing work to depend on a released version
of the [EISOP] fork instead.)
This project depends on the [EISOP Checker Framework][EISOP].

To codevelop changes with the EISOP Checker Framework, clone it into the
sibling directory `../checker-framwork` and pass
`--include-build path/to/checker-framework` to Gradle when building
this project.

Because of that dependency, this build clones that unreleased fork into the
sibling directory `../checker-framwork`.
_That_ build then clones some other projects into other sibling directories. It
expects `../jdk` to contain an annotated JDK, so our build
clones [JSpecify's][jspecify-jdk] there.
Expand All @@ -29,7 +29,7 @@ clone the repo (or your fork) somewhere, and pass
`--include-build path/to/jspecify` to Gradle when building. The local clone will
be used for both the annotations and the conformance test suite.

By default the reference checker depends on version `0.3.0` of the annotations,
By default the reference checker depends on version `1.0.0` of the annotations,
and version `0.0.0-SNAPSHOT` of the conformance test suite.

In order to depend on a different published version of either artifact, set
Expand All @@ -40,7 +40,6 @@ Gradle properties on the command line.
of the conformance test suite.

[EISOP]: https://github.com/eisop/checker-framework
[jspecify-checker-framework]: https://github.com/jspecify/checker-framework
[jspecify-jdk]: https://github.com/jspecify/jdk
[jspecify-jspecify]: https://github.com/jspecify/jspecify
[main-eisop branch]: https://github.com/jspecify/jspecify-reference-checker/tree/main-eisop
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
org.jspecify\:jspecify=0.3.0
org.jspecify\:jspecify=1.0.0
org.jspecify.conformance\:conformance-test-framework=0.0.0-SNAPSHOT
org.jspecify.conformance\:conformance-tests=0.0.0-SNAPSHOT
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Loading
Loading