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

Create gradle build files for review #1

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf

# These are Windows script files and should use crlf
*.bat text eol=crlf

39 changes: 39 additions & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on: [push, pull_request]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build-and-test:
# The type of runner that the job will run on
runs-on: ubuntu-latest
defaults:
run:
working-directory: checker-framework-jspecify-conformance
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Check out CF JSpecify Conformance Tests
uses: actions/checkout@v4
with:
path: checker-framework-jspecify-conformance
- name: Check out Checker Framework
uses: actions/checkout@v4
with:
repository: eisop/checker-framework
path: checker-framework
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: Set up Gradle
uses: gradle/gradle-build-action@v3
- name: Build and Test
run: ./gradlew assemble runJSpecifyConformanceTests -PcfLocal
env:
CHECKERFRAMEWORK: ./checker-framework
24 changes: 6 additions & 18 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
# Compiled class file
*.class
# Ignore Gradle project-specific cache directory
.gradle

# Log file
*.log
# Ignore Gradle build output directory
build

# BlueJ files
*.ctxt
# Ignore vscode settings
.vscode

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
152 changes: 152 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html
*/

plugins {


id 'java-library'

// Code formatting; defines targets "spotlessApply" and "spotlessCheck"
// Requires JDK 11 or higher; the plugin crashes under JDK 8.
id 'com.diffplug.spotless' version '6.25.0'

// Checker Framework pluggable type-checking
id 'org.checkerframework' version '0.6.37'
}

repositories {
// Snapshot repository for JSpecify conformance test framework
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots'}
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/'}
// Use Maven Central for resolving dependencies.
mavenCentral()
}

configurations {
jSpecifyConformanceTests
}

dependencies {
// Use JUnit Jupiter for testing.
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter:5.9.1'

// This dependency is used by the application.
implementation 'com.google.guava:guava:31.1-jre'

testImplementation 'org.jspecify:jspecify:0.3.0'

testImplementation 'org.jspecify.conformance:conformance-test-framework:0.0.0-SNAPSHOT'
jSpecifyConformanceTests 'org.jspecify.conformance:conformance-tests:0.0.0-SNAPSHOT'
}

spotless {
format 'misc', {
// define the files to apply `misc` to
target '*.md', '.gitignore'

// define the steps to apply to those files
trimTrailingWhitespace()
indentWithSpaces(2)
endWithNewline()
}
java {
googleJavaFormat()
formatAnnotations()
}
groovyGradle {
target '**/*.gradle'
greclipse() // which formatter Spotless should use to format .gradle files.
indentWithSpaces(2)
trimTrailingWhitespace()
// endWithNewline() // Don't want to end empty files with a newline
}
}

apply plugin: 'org.checkerframework'

dependencies {
compileOnly 'io.github.eisop:checker-qual:3.42.0-eisop2'
testCompileOnly 'io.github.eisop:checker-qual:3.42.0-eisop2'
checkerFramework 'io.github.eisop:checker:3.42.0-eisop2'
}

checkerFramework {
checkers = [
// No need to run CalledMethodsChecker, because ResourceLeakChecker does so.
// 'org.checkerframework.checker.calledmethods.CalledMethodsChecker',
'org.checkerframework.checker.formatter.FormatterChecker',
'org.checkerframework.checker.index.IndexChecker',
'org.checkerframework.checker.interning.InterningChecker',
'org.checkerframework.checker.lock.LockChecker',
'org.checkerframework.checker.nullness.NullnessChecker',
'org.checkerframework.checker.regex.RegexChecker',
'org.checkerframework.checker.resourceleak.ResourceLeakChecker',
'org.checkerframework.checker.signature.SignatureChecker',
'org.checkerframework.checker.signedness.SignednessChecker',
'org.checkerframework.common.initializedfields.InitializedFieldsChecker',
]
extraJavacArgs = [
'-Werror',
'-AcheckPurityAnnotations',
'-ArequirePrefixInWarningSuppressions',
'-AwarnRedundantAnnotations',
'-AwarnUnneededSuppressions',
'-AnoJreVersionCheck',
'-Aversion',
]
}
// To use a locally-built Checker Framework, run gradle with "-PcfLocal".
if (project.hasProperty('cfLocal')) {
def cfHome = String.valueOf(System.getenv('CHECKERFRAMEWORK'))
dependencies {
compileOnly(files(cfHome + '/checker/dist/checker-qual.jar'))
testCompileOnly(files(cfHome + '/checker/dist/checker-qual.jar'))
checkerFramework files(cfHome + '/checker/dist/checker.jar')
}
}

tasks.named('test') {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

// Unzip JSpecify conformance tests using the artifact
task unzipJSpecifyConformanceTestSuite(type: Copy) {
description 'Unzips the JSpecify conformance test suite into the build directory.'

dependsOn(configurations.jSpecifyConformanceTests)
copy {
from zipTree(configurations.jSpecifyConformanceTests.singleFile)
into "${buildDir}/jspecify-conformance-tests"
}
}

// Run JSpecify conformance tests
task runJSpecifyConformanceTests(type: Test, group: 'Verification') {
description 'Runs the JSpecify conformance tests.'
include '**/NullnessJSpecifyConformanceTest.class'

//shouldRunAfter test

environment 'JSPECIFY_CONFORMANCE_TEST_MODE', 'WRITE'

// Conformance tests
inputs.files(unzipJSpecifyConformanceTestSuite)
inputs.files("${projectDir}/src/test/resources/jspecify-conformance-test-report.txt")

doFirst {
systemProperties([
"ConformanceTest.inputs": "${buildDir}/jspecify-conformance-tests/assertions/org/jspecify/conformance/tests",
"ConformanceTest.report": "${projectDir}/src/test/resources/jspecify-conformance-test-report.txt",
"ConformanceTest.deps" : fileTree("${buildDir}/jspecify-conformance-tests/deps").join(":")
])
}
}

//test.finalizedBy(runJSpecifyConformanceTests)
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package jspecify.conformance;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.checkerframework.checker.nullness.NullnessChecker;
import org.checkerframework.framework.test.TestConfiguration;
import org.checkerframework.framework.test.TestConfigurationBuilder;
import org.checkerframework.framework.test.TestUtilities;
import org.checkerframework.framework.test.TypecheckExecutor;
import org.checkerframework.framework.test.TypecheckResult;
import org.jspecify.conformance.ConformanceTestRunner;
import org.jspecify.conformance.ReportedFact;
import org.junit.Test;

/** An object to run the conformance tests against the EISOP Checker Framework. */
public final class NullnessJSpecifyConformanceTest {

/** Directory of the JSpecify Conformance Tests. */
private final Path testDir;

/** Location of the report. */
private final Path reportPath;

/** JSpecify conformance test dependencies. */
private final ImmutableList<Path> deps;

/** Options to pass to the checker. */
private static final ImmutableList<String> TEST_OPTIONS =
ImmutableList.of("-AassumePure", "-Adetailedmsgtext");

/** Create a NullnessJSpecifyConformanceTest. */
public NullnessJSpecifyConformanceTest() {
System.out.println("HIIII");
this.testDir = getSystemPropertyPath("ConformanceTest.inputs");
this.reportPath = getSystemPropertyPath("ConformanceTest.report");
this.deps =
Splitter.on(":").splitToList(System.getProperty("ConformanceTest.deps")).stream()
.map(dep -> Paths.get(dep))
.collect(toImmutableList());
}

/**
* Get an equivalent path from a system property.
*
* @param propertyName the name of the property.
*/
private Path getSystemPropertyPath(String propertyName) {
String path = System.getProperty(propertyName);
if (path == null) {
throw new IllegalArgumentException("System property " + propertyName + " not set");
}
return Paths.get(path);
}

/** Run the conformance tests. */
@Test
public void conformanceTests() throws IOException {
ConformanceTestRunner runner =
new ConformanceTestRunner(NullnessJSpecifyConformanceTest::analyze);
runner.checkConformance(testDir, deps, reportPath);
}

/**
* Analyze the conformance tests by comparing reported facts against expected facts.
*
* @param testDir the directory of the conformance tests.
* @param files the files to analyze.
* @param deps the dependencies of the conformance tests.
*/
private static ImmutableSet<ReportedFact> analyze(
Path testDir, ImmutableList<Path> files, ImmutableList<Path> deps) {
ImmutableSet<File> fileInputs = files.stream().map(Path::toFile).collect(toImmutableSet());

ImmutableList<String> depsAsStrings =
deps.stream().map(Path::toString).collect(toImmutableList());

TestConfiguration testConfig =
TestConfigurationBuilder.buildDefaultConfiguration(
null,
fileInputs,
depsAsStrings,
ImmutableList.of(NullnessChecker.class.getName()),
TEST_OPTIONS,
TestUtilities.getShouldEmitDebugInfo());
TypecheckExecutor typecheckExecutor = new TypecheckExecutor();
TypecheckResult result = typecheckExecutor.runTest(testConfig);
ImmutableSet<ReportedFact> reportedFacts =
result.getUnexpectedDiagnostics().stream()
.map(
diagnostic ->
new ReportedFactMessage(
Path.of(diagnostic.getFilename()),
diagnostic.getLineNumber(),
diagnostic.getMessage()))
.collect(toImmutableSet());
return reportedFacts;
}
}

/** A reported fact with a message as a string. */
final class ReportedFactMessage extends ReportedFact {

/** The message that the fact describes. */
private final String message;

/**
* Create a ReportedFactMessage.
*
* @param filename the file that the fact is in.
* @param lineNumber the line number of the fact.
* @param message the message that the fact describes.
*/
ReportedFactMessage(Path filename, long lineNumber, String message) {
super(filename, lineNumber);
this.message = requireNonNull(message);
}

/** Indicates if the fact must be an expected fact. */
@Override
protected boolean mustBeExpected() {
return false;
}

/** Get the message that the fact describes. */
@Override
protected String getFactText() {
return message;
}
}
Empty file.
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading
Loading