framework.src.org.checkerframework.framework.test.TypecheckExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java’s type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.framework.test;
import org.checkerframework.framework.test.diagnostics.JavaDiagnosticReader;
import org.checkerframework.framework.test.diagnostics.TestDiagnostic;
import org.checkerframework.framework.util.PluginUtil;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Used by the Checker Framework test suite to run the framework and generate a test result.
*/
public class TypecheckExecutor {
public TypecheckExecutor() {
}
/**
* Runs a typechecking test using the given configuration and returns the
* test result
*/
public TypecheckResult runTest(TestConfiguration configuration) {
CompilationResult result = compile(configuration);
return interpretResults(configuration, result);
}
/**
* Using the settings from the input configuration, compile all source files in the configuration,
* and return place the result in a CompilationResult
*/
public CompilationResult compile(TestConfiguration configuration) {
TestUtilities.ensureDirectoryExists(new File(configuration.getOptions().get("-d")));
final StringWriter javacOutput = new StringWriter();
DiagnosticCollector diagnostics = new
DiagnosticCollector();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable javaFiles =
fileManager.getJavaFileObjects(configuration.getTestSourceFiles().toArray(new File[]{}));
// Even though the method compilergetTask takes a list of processors, it fails if processors are passed this way
// with the message:
// error: Class names, 'org.checkerframework.checker.interning.InterningChecker', are only accepted if
// annotation processing is explicitly requested
// Therefore, we now add them to the beginning of the options list
final List options = new ArrayList();
options.add("-processor");
options.add(PluginUtil.join(",", configuration.getProcessors()));
List nonJvmOptions = new ArrayList();
for (String option : configuration.getFlatOptions()) {
if (! option.startsWith("-J-")) {
nonJvmOptions.add(option);
}
}
options.addAll(nonJvmOptions);
if (configuration.shouldEmitDebugInfo()) {
System.out.println("Running test using the following invocation:");
System.out.println("javac " + PluginUtil.join(" ", options) + " "
+ PluginUtil.join(" ", configuration.getTestSourceFiles()));
}
JavaCompiler.CompilationTask task =
compiler.getTask(javacOutput, fileManager, diagnostics, options, new ArrayList(), javaFiles);
/*
* In Eclipse, std out and std err for multiple tests appear as one
* long stream. When selecting a specific failed test, one sees the
* expected/unexpected messages, but not the std out/err messages from
* that particular test. Can we improve this somehow?
*/
final Boolean compiledWithoutError = task.call();
javacOutput.flush();
return new CompilationResult(compiledWithoutError, javacOutput.toString(), javaFiles,
diagnostics.getDiagnostics());
}
/**
* Reads the expected diagnostics for the given configuration and creates a TypecheckResult
* which contains all of the missing and expected diagnostics
*/
public TypecheckResult interpretResults(TestConfiguration config, CompilationResult compilationResult) {
List expectedDiagnostics = readDiagnostics(config, compilationResult);
return TypecheckResult.fromCompilationResults(config, compilationResult, expectedDiagnostics);
}
/**
* Added in case a subclass wishes to filter out errors or add new expected errors. This method is called immediately
* before results are checked.
*/
protected List readDiagnostics(TestConfiguration config, CompilationResult compilationResult) {
List expectedDiagnostics;
if (config.getDiagnosticFiles() == null || config.getDiagnosticFiles().isEmpty()) {
expectedDiagnostics = JavaDiagnosticReader.readExpectedDiagnosticsJfo(compilationResult.getJavaFileObjects(), true);
} else {
expectedDiagnostics = JavaDiagnosticReader.readDiagnosticFiles(config.getDiagnosticFiles(), true);
}
return expectedDiagnostics;
}
}