blob: 51f92dec39ab7f6140b7bd9f3828cf6549fc9cbc [file] [log] [blame]
// Note that "-processor org/checkerframework/checker.nullness.NullnessChecker"
// is added to the invocation of the compiler!
// TODO: add a @Processor method-annotation to parameterize
/**
* This class has auxiliary methods to compile a class and return its classfile. It is used by
* defaultPersists/Driver and inheritDeclAnnoPersist/Driver.
*/
import com.sun.tools.classfile.ClassFile;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.StringJoiner;
public class PersistUtil {
public static String testClassOf(Method m) {
TestClass tc = m.getAnnotation(TestClass.class);
if (tc != null) {
return tc.value();
} else {
return "Test";
}
}
public static ClassFile compileAndReturn(String fullFile, String testClass) throws Exception {
File source = writeTestFile(fullFile);
File clazzFile = compileTestFile(source, testClass);
return ClassFile.read(clazzFile);
}
public static File writeTestFile(String fullFile) throws IOException {
File f = new File("Test.java");
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
out.println(fullFile);
out.close();
return f;
}
public static File compileTestFile(File f, String testClass) {
int rc =
com.sun.tools.javac.Main.compile(
new String[] {
"-source",
"1.8",
"-g",
"-processor",
"org.checkerframework.checker.nullness.NullnessChecker",
f.getPath()
});
if (rc != 0) {
throw new Error("compilation failed. rc=" + rc);
}
String path;
if (f.getParent() != null) {
path = f.getParent();
} else {
path = "";
}
return new File(path + testClass + ".class");
}
public static String wrap(String compact) {
StringJoiner sj = new StringJoiner(System.lineSeparator());
// Automatically import java.util
sj.add("");
sj.add("import java.util.*;");
sj.add("import java.lang.annotation.*;");
// And the Nullness qualifiers
sj.add("import org.checkerframework.framework.qual.DefaultQualifier;");
sj.add("import org.checkerframework.checker.nullness.qual.*;");
sj.add("import org.checkerframework.dataflow.qual.*;");
sj.add("");
boolean isSnippet =
!(compact.startsWith("class") || compact.contains(" class"))
&& !compact.contains("interface")
&& !compact.contains("enum");
if (isSnippet) {
sj.add("class Test {");
}
sj.add(compact);
if (isSnippet) {
sj.add("}");
sj.add("");
}
return sj.toString();
}
}
/**
* The name of the class that should be analyzed. Should only need to be provided when analyzing
* inner classes.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface TestClass {
String value() default "Test";
}