use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class WholeProgramInferenceJavaParserStorage method writeResultsToFile.
@Override
public void writeResultsToFile(OutputFormat outputFormat, BaseTypeChecker checker) {
if (outputFormat != OutputFormat.AJAVA) {
throw new BugInCF("WholeProgramInferenceJavaParser used with format " + outputFormat);
}
File outputDir = new File(AJAVA_FILES_PATH);
if (!outputDir.exists()) {
outputDir.mkdirs();
}
for (String path : modifiedFiles) {
CompilationUnitAnnos root = sourceToAnnos.get(path);
prepareCompilationUnitForWriting(root);
root.transferAnnotations(checker);
String packageDir = AJAVA_FILES_PATH;
if (root.compilationUnit.getPackageDeclaration().isPresent()) {
packageDir += File.separator + root.compilationUnit.getPackageDeclaration().get().getNameAsString().replaceAll("\\.", File.separator);
}
File packageDirFile = new File(packageDir);
if (!packageDirFile.exists()) {
packageDirFile.mkdirs();
}
String name = new File(path).getName();
if (name.endsWith(".java")) {
name = name.substring(0, name.length() - ".java".length());
}
name += "-" + checker.getClass().getCanonicalName() + ".ajava";
String outputPath = packageDir + File.separator + name;
try {
FileWriter writer = new FileWriter(outputPath);
// JavaParser can output using lexical preserving printing, which writes the file such that
// its formatting is close to the original source file it was parsed from as
// possible. Currently, this feature is very buggy and crashes when adding annotations in
// certain locations. This implementation could be used instead if it's fixed in JavaParser.
// LexicalPreservingPrinter.print(root.declaration, writer);
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
writer.write(prettyPrinter.print(root.compilationUnit));
writer.close();
} catch (IOException e) {
throw new BugInCF("Error while writing ajava file " + outputPath, e);
}
}
modifiedFiles.clear();
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class WholeProgramInferenceJavaParserStorage method addClassesForElement.
/**
* Calls {@link #addSourceFile(String)} for the file containing the given element.
*
* @param element the element for the source file to add
* @return path of the file containing {@code element}
*/
private String addClassesForElement(Element element) {
if (!ElementUtils.isElementFromSourceCode(element)) {
throw new BugInCF("Called addClassesForElement for non-source element: " + element);
}
TypeElement toplevelClass = ElementUtils.toplevelEnclosingTypeElement(element);
String path = ElementUtils.getSourceFilePath(toplevelClass);
if (classToAnnos.containsKey(ElementUtils.getBinaryName(toplevelClass))) {
return path;
}
addSourceFile(path);
CompilationUnitAnnos sourceAnnos = sourceToAnnos.get(path);
ClassTree toplevelClassTree = (ClassTree) atypeFactory.declarationFromElement(toplevelClass);
TypeDeclaration<?> javaParserNode = sourceAnnos.getClassOrInterfaceDeclarationByName(toplevelClass.getSimpleName().toString());
createWrappersForClass(toplevelClassTree, javaParserNode, sourceAnnos);
return path;
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class ASceneWrapper method writeToFile.
/**
* Write the scene wrapped by this object to a file at the given path.
*
* @param jaifPath the path of the file to be written, but ending in ".jaif". If {@code
* outputformat} is not {@code JAIF}, the path will be modified to match.
* @param annosToIgnore which annotations should be ignored in which contexts
* @param outputFormat the output format to use
* @param checker the checker from which this method is called, for naming stub files
*/
public void writeToFile(String jaifPath, AnnotationsInContexts annosToIgnore, OutputFormat outputFormat, BaseTypeChecker checker) {
assert jaifPath.endsWith(".jaif");
AScene scene = theScene.clone();
removeAnnosFromScene(scene, annosToIgnore);
scene.prune();
String filepath;
switch(outputFormat) {
case JAIF:
filepath = jaifPath;
break;
case STUB:
String astubWithChecker = "-" + checker.getClass().getCanonicalName() + ".astub";
filepath = jaifPath.replace(".jaif", astubWithChecker);
break;
default:
throw new BugInCF("Unhandled outputFormat " + outputFormat);
}
new File(filepath).delete();
// Only write non-empty scenes into files.
if (!scene.isEmpty()) {
try {
switch(outputFormat) {
case STUB:
// For stub files, pass in the checker to compute contracts on the fly; precomputing
// yields incorrect annotations, most likely due to nested classes.
SceneToStubWriter.write(this, filepath, checker);
break;
case JAIF:
// nothing about (and cannot depend on) the Checker Framework.
for (Map.Entry<String, AClass> classEntry : scene.classes.entrySet()) {
AClass aClass = classEntry.getValue();
for (Map.Entry<String, AMethod> methodEntry : aClass.getMethods().entrySet()) {
AMethod aMethod = methodEntry.getValue();
List<AnnotationMirror> contractAnnotationMirrors = checker.getTypeFactory().getContractAnnotations(aMethod);
List<Annotation> contractAnnotations = CollectionsPlume.mapList(AnnotationConverter::annotationMirrorToAnnotation, contractAnnotationMirrors);
aMethod.contracts = contractAnnotations;
}
}
IndexFileWriter.write(scene, new FileWriter(filepath));
break;
default:
throw new BugInCF("Unhandled outputFormat " + outputFormat);
}
} catch (IOException e) {
throw new UserError("Problem while writing %s: %s", filepath, e.getMessage());
} catch (DefException e) {
throw new BugInCF(e);
}
}
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class ASceneWrapper method updateSymbolInformation.
/**
* Updates the symbol information stored in AClass for the given class. May be called multiple
* times (and needs to be if the second parameter was null the first time it was called; only some
* calls provide the symbol information).
*
* @param aClass the class representation in which the symbol information is to be updated
* @param classSymbol the source of the symbol information; may be null, in which case this method
* does nothing
*/
public void updateSymbolInformation(AClass aClass, @Nullable ClassSymbol classSymbol) {
if (classSymbol == null) {
return;
}
if (classSymbol.isEnum()) {
List<VariableElement> enumConstants = new ArrayList<>();
for (Element e : ((TypeElement) classSymbol).getEnclosedElements()) {
if (e.getKind() == ElementKind.ENUM_CONSTANT) {
enumConstants.add((VariableElement) e);
}
}
if (!aClass.isEnum(classSymbol.getSimpleName().toString())) {
aClass.setEnumConstants(enumConstants);
} else {
// Verify that the existing value is consistent.
List<VariableElement> existingEnumConstants = aClass.getEnumConstants();
if (existingEnumConstants.size() != enumConstants.size()) {
throw new BugInCF("inconsistent enum constants in WPI for class " + classSymbol.getQualifiedName().toString());
}
for (int i = 0; i < enumConstants.size(); i++) {
if (!existingEnumConstants.get(i).equals(enumConstants.get(i))) {
throw new BugInCF("inconsistent enum constants in WPI for class " + classSymbol.getQualifiedName().toString());
}
}
}
}
ClassSymbol outerClass = classSymbol;
ClassSymbol previous = classSymbol;
do {
if (outerClass.isEnum()) {
aClass.markAsEnum(outerClass.getSimpleName().toString());
}
Element element = classSymbol.getEnclosingElement();
if (element == null || element.getKind() == ElementKind.PACKAGE) {
break;
}
TypeElement t = ElementUtils.enclosingTypeElement(element);
previous = outerClass;
outerClass = (ClassSymbol) t;
// It is necessary to check that previous isn't equal to outer class because
// otherwise this loop will sometimes run forever.
} while (outerClass != null && !previous.equals(outerClass));
aClass.setTypeElement(classSymbol);
}
use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.
the class JointJavacJavaParserVisitor method visitMethodInvocation.
@Override
public Void visitMethodInvocation(MethodInvocationTree javacTree, Node javaParserNode) {
if (javaParserNode instanceof MethodCallExpr) {
MethodCallExpr node = (MethodCallExpr) javaParserNode;
processMethodInvocation(javacTree, node);
// JavaParser the type arguments will have the none Optional value.
assert javacTree.getTypeArguments().isEmpty() != node.getTypeArguments().isPresent();
if (!javacTree.getTypeArguments().isEmpty()) {
visitLists(javacTree.getTypeArguments(), node.getTypeArguments().get());
}
// In JavaParser, the method name itself and receiver are stored as fields of the
// invocation itself, but in javac they might be combined into one MemberSelectTree.
// That member select may also be a single IdentifierTree if no receiver was written.
// This requires one layer of unnesting.
ExpressionTree methodSelect = javacTree.getMethodSelect();
if (methodSelect.getKind() == Tree.Kind.IDENTIFIER) {
methodSelect.accept(this, node.getName());
} else if (methodSelect.getKind() == Tree.Kind.MEMBER_SELECT) {
MemberSelectTree selection = (MemberSelectTree) methodSelect;
assert node.getScope().isPresent();
selection.getExpression().accept(this, node.getScope().get());
} else {
throw new BugInCF("Unexpected method selection type: %s", methodSelect);
}
visitLists(javacTree.getArguments(), node.getArguments());
} else if (javaParserNode instanceof ExplicitConstructorInvocationStmt) {
ExplicitConstructorInvocationStmt node = (ExplicitConstructorInvocationStmt) javaParserNode;
processMethodInvocation(javacTree, node);
assert javacTree.getTypeArguments().isEmpty() != node.getTypeArguments().isPresent();
if (!javacTree.getTypeArguments().isEmpty()) {
visitLists(javacTree.getTypeArguments(), node.getTypeArguments().get());
}
visitLists(javacTree.getArguments(), node.getArguments());
} else {
throwUnexpectedNodeType(javacTree, javaParserNode);
}
return null;
}
Aggregations