Search in sources :

Example 51 with BugInCF

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();
}
Also used : DefaultPrettyPrinter(com.github.javaparser.printer.DefaultPrettyPrinter) FileWriter(java.io.FileWriter) IOException(java.io.IOException) BugInCF(org.checkerframework.javacutil.BugInCF) File(java.io.File)

Example 52 with BugInCF

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;
}
Also used : TypeElement(javax.lang.model.element.TypeElement) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) BugInCF(org.checkerframework.javacutil.BugInCF)

Example 53 with BugInCF

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);
        }
    }
}
Also used : AScene(scenelib.annotations.el.AScene) AnnotationConverter(org.checkerframework.common.wholeprograminference.AnnotationConverter) UserError(org.checkerframework.javacutil.UserError) DefException(scenelib.annotations.el.DefException) IndexFileWriter(scenelib.annotations.io.IndexFileWriter) FileWriter(java.io.FileWriter) IOException(java.io.IOException) BugInCF(org.checkerframework.javacutil.BugInCF) Annotation(scenelib.annotations.Annotation) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AClass(scenelib.annotations.el.AClass) File(java.io.File) Map(java.util.Map) AMethod(scenelib.annotations.el.AMethod)

Example 54 with BugInCF

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);
}
Also used : TypeElement(javax.lang.model.element.TypeElement) ATypeElement(scenelib.annotations.el.ATypeElement) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ATypeElement(scenelib.annotations.el.ATypeElement) Element(javax.lang.model.element.Element) ArrayList(java.util.ArrayList) VariableElement(javax.lang.model.element.VariableElement) BugInCF(org.checkerframework.javacutil.BugInCF)

Example 55 with BugInCF

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;
}
Also used : MemberSelectTree(com.sun.source.tree.MemberSelectTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExplicitConstructorInvocationStmt(com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt) BugInCF(org.checkerframework.javacutil.BugInCF) MethodCallExpr(com.github.javaparser.ast.expr.MethodCallExpr)

Aggregations

BugInCF (org.checkerframework.javacutil.BugInCF)127 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)29 ArrayList (java.util.ArrayList)28 AnnotationMirror (javax.lang.model.element.AnnotationMirror)26 TypeElement (javax.lang.model.element.TypeElement)26 TypeMirror (javax.lang.model.type.TypeMirror)25 ExecutableElement (javax.lang.model.element.ExecutableElement)24 MethodTree (com.sun.source.tree.MethodTree)20 ExpressionTree (com.sun.source.tree.ExpressionTree)18 VariableTree (com.sun.source.tree.VariableTree)18 Element (javax.lang.model.element.Element)18 ClassTree (com.sun.source.tree.ClassTree)17 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)17 NewClassTree (com.sun.source.tree.NewClassTree)17 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)16 IOException (java.io.IOException)16 Tree (com.sun.source.tree.Tree)15 Map (java.util.Map)15 List (java.util.List)14 VariableElement (javax.lang.model.element.VariableElement)14