Search in sources :

Example 1 with FullyQualifiedName

use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.

the class CheckerMain method getAllCheckerClassNames.

/**
 * Returns the list of fully qualified names of the checkers found in checker.jar. This covers
 * only checkers with the name ending in "Checker". Checkers with a name ending in "Subchecker"
 * are not included in the returned list. Note however that it is possible for a checker with the
 * name ending in "Checker" to be used as a subchecker.
 *
 * @return fully qualified names of the checkers found in checker.jar
 */
private List<@FullyQualifiedName String> getAllCheckerClassNames() {
    ArrayList<@FullyQualifiedName String> checkerClassNames = new ArrayList<>();
    try {
        final JarInputStream checkerJarIs = new JarInputStream(new FileInputStream(checkerJar));
        ZipEntry entry;
        while ((entry = checkerJarIs.getNextEntry()) != null) {
            final String name = entry.getName();
            // Checkers ending in "Subchecker" are not included in this list used by CheckerMain.
            if ((name.startsWith(CHECKER_BASE_DIR_NAME) || name.startsWith(COMMON_BASE_DIR_NAME)) && name.endsWith("Checker.class")) {
                // Forward slash is used instead of File.separator because checker.jar uses / as
                // the separator.
                // string manipulation
                @SuppressWarnings("signature") @FullyQualifiedName String fqName = String.join(".", name.substring(0, name.length() - ".class".length()).split("/"));
                checkerClassNames.add(fqName);
            }
        }
        checkerJarIs.close();
    } catch (IOException e) {
        // Issue a warning instead of aborting execution.
        System.err.printf("Could not read %s. Shorthand processor names will not work.%n", checkerJar);
    }
    return checkerClassNames;
}
Also used : JarInputStream(java.util.jar.JarInputStream) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream)

Example 2 with FullyQualifiedName

use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.

the class AnnotationFileParser method getImportableMembers.

/**
 * Get all members of a Type that are importable in an annotation file. Currently these are values
 * of enums, or compile time constants.
 *
 * @param typeElement the type whose members to return
 * @return a list of fully-qualified member names
 */
private static List<@FullyQualifiedName String> getImportableMembers(TypeElement typeElement) {
    List<VariableElement> memberElements = ElementFilter.fieldsIn(typeElement.getEnclosedElements());
    List<@FullyQualifiedName String> result = new ArrayList<>();
    for (VariableElement varElement : memberElements) {
        if (varElement.getConstantValue() != null || varElement.getKind() == ElementKind.ENUM_CONSTANT) {
            // string concatenation
            @SuppressWarnings("signature") @FullyQualifiedName String fqName = typeElement.getQualifiedName().toString() + "." + varElement.getSimpleName().toString();
            result.add(fqName);
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) VariableElement(javax.lang.model.element.VariableElement)

Example 3 with FullyQualifiedName

use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.

the class TypeAnnotationMover method getAnnotationDeclaration.

/**
 * Returns the TypeElement for an annotation, or null if it cannot be found.
 *
 * @param annotation a JavaParser annotation
 * @return the TypeElement for {@code annotation}, or null if it cannot be found
 */
@Nullable
private TypeElement getAnnotationDeclaration(AnnotationExpr annotation) {
    // https://tinyurl.com/cfissue/3094
    @SuppressWarnings("signature") @FullyQualifiedName String annoNameFq = annotation.getNameAsString();
    TypeElement annoTypeElt = allAnnotations.get(annoNameFq);
    if (annoTypeElt == null) {
        annoTypeElt = elements.getTypeElement(annoNameFq);
        if (annoTypeElt == null) {
            // Not a supported annotation.
            return null;
        }
        AnnotationFileParser.putAllNew(allAnnotations, AnnotationFileParser.createNameToAnnotationMap(Collections.singletonList(annoTypeElt)));
    }
    return annoTypeElt;
}
Also used : TypeElement(javax.lang.model.element.TypeElement) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 4 with FullyQualifiedName

use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.

the class AnnotationFileParser method processTypeDecl.

/**
 * Process a type declaration: copy its annotations to {@code #annotationFileAnnos}.
 *
 * <p>This method stores the declaration's type parameters in {@link #typeParameters}. When
 * processing an ajava file, where traversal is handled externaly by a {@link
 * org.checkerframework.framework.ajava.JointJavacJavaParserVisitor}, these type variables must be
 * removed after processing the type's members. Otherwise, this method removes them.
 *
 * @param typeDecl the type declaration to process
 * @param outertypeName the name of the containing class, when processing a nested class;
 *     otherwise null
 * @param classTree the tree corresponding to typeDecl if processing an ajava file, null otherwise
 * @return a list of types variables for {@code typeDecl}. Only non-null if processing an ajava
 *     file, in which case the contents should be removed from {@link #typeParameters} after
 *     processing the type declaration's members
 */
private List<AnnotatedTypeVariable> processTypeDecl(TypeDeclaration<?> typeDecl, String outertypeName, @Nullable ClassTree classTree) {
    assert typeBeingParsed != null;
    if (skipNode(typeDecl)) {
        return null;
    }
    String innerName;
    @FullyQualifiedName String fqTypeName;
    TypeElement typeElt;
    if (classTree != null) {
        typeElt = TreeUtils.elementFromDeclaration(classTree);
        innerName = typeElt.getQualifiedName().toString();
        typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
        fqTypeName = typeBeingParsed.toString();
    } else {
        String packagePrefix = outertypeName == null ? "" : outertypeName + ".";
        innerName = packagePrefix + typeDecl.getNameAsString();
        typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
        fqTypeName = typeBeingParsed.toString();
        typeElt = elements.getTypeElement(fqTypeName);
    }
    if (!isAnnotatedForThisChecker(typeDecl.getAnnotations())) {
        return null;
    }
    if (typeElt == null) {
        if (debugAnnotationFileParser || (!warnIfNotFoundIgnoresClasses && !hasNoAnnotationFileParserWarning(typeDecl.getAnnotations()) && !hasNoAnnotationFileParserWarning(packageAnnos))) {
            if (elements.getAllTypeElements(fqTypeName).isEmpty()) {
                stubWarnNotFound(typeDecl, "Type not found: " + fqTypeName);
            } else {
                stubWarnNotFound(typeDecl, "Type not found uniquely: " + fqTypeName + " : " + elements.getAllTypeElements(fqTypeName));
            }
        }
        return null;
    }
    List<AnnotatedTypeVariable> typeDeclTypeParameters = null;
    if (typeElt.getKind() == ElementKind.ENUM) {
        if (!(typeDecl instanceof EnumDeclaration)) {
            warn(typeDecl, innerName + " is an enum, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
            return null;
        }
        typeDeclTypeParameters = processEnum((EnumDeclaration) typeDecl, typeElt);
        typeParameters.addAll(typeDeclTypeParameters);
    } else if (typeElt.getKind() == ElementKind.ANNOTATION_TYPE) {
        if (!(typeDecl instanceof AnnotationDeclaration)) {
            warn(typeDecl, innerName + " is an annotation, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
            return null;
        }
        stubWarnNotFound(typeDecl, "Skipping annotation type: " + fqTypeName);
    } else if (typeDecl instanceof ClassOrInterfaceDeclaration) {
        if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
            warn(typeDecl, innerName + " is a class or interface, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
            return null;
        }
        typeDeclTypeParameters = processType(typeDecl, typeElt);
        typeParameters.addAll(typeDeclTypeParameters);
    } else if (typeDecl instanceof RecordDeclaration) {
        typeDeclTypeParameters = processType(typeDecl, typeElt);
        typeParameters.addAll(typeDeclTypeParameters);
    }
    // of this method.
    if (fileType == AnnotationFileType.AJAVA) {
        return typeDeclTypeParameters;
    }
    if (typeDecl instanceof RecordDeclaration) {
        NodeList<Parameter> recordMembers = ((RecordDeclaration) typeDecl).getParameters();
        LinkedHashMap<String, RecordComponentStub> byName = new LinkedHashMap<>();
        for (Parameter recordMember : recordMembers) {
            RecordComponentStub stub = processRecordField(recordMember, findFieldElement(typeElt, recordMember.getNameAsString(), recordMember));
            byName.put(recordMember.getNameAsString(), stub);
        }
        annotationFileAnnos.records.put(typeDecl.getFullyQualifiedName().get(), new RecordStub(byName));
    }
    Pair<Map<Element, BodyDeclaration<?>>, Map<Element, List<BodyDeclaration<?>>>> members = getMembers(typeDecl, typeElt, typeDecl);
    for (Map.Entry<Element, BodyDeclaration<?>> entry : members.first.entrySet()) {
        final Element elt = entry.getKey();
        final BodyDeclaration<?> decl = entry.getValue();
        switch(elt.getKind()) {
            case FIELD:
                processField((FieldDeclaration) decl, (VariableElement) elt);
                break;
            case ENUM_CONSTANT:
                // the TRACKER enum constant annotated with DefaultType:
                if (decl instanceof FieldDeclaration) {
                    processField((FieldDeclaration) decl, (VariableElement) elt);
                } else if (decl instanceof EnumConstantDeclaration) {
                    processEnumConstant((EnumConstantDeclaration) decl, (VariableElement) elt);
                } else {
                    throw new BugInCF("Unexpected decl type " + decl.getClass() + " for ENUM_CONSTANT kind, original: " + decl);
                }
                break;
            case CONSTRUCTOR:
            case METHOD:
                processCallableDeclaration((CallableDeclaration<?>) decl, (ExecutableElement) elt);
                break;
            case CLASS:
            case INTERFACE:
                // Not processing an ajava file, so ignore the return value.
                processTypeDecl((ClassOrInterfaceDeclaration) decl, innerName, null);
                break;
            case ENUM:
                // Not processing an ajava file, so ignore the return value.
                processTypeDecl((EnumDeclaration) decl, innerName, null);
                break;
            default:
                /* do nothing */
                stubWarnNotFound(decl, "AnnotationFileParser ignoring: " + elt);
                break;
        }
    }
    for (Map.Entry<Element, List<BodyDeclaration<?>>> entry : members.second.entrySet()) {
        ExecutableElement fakeOverridden = (ExecutableElement) entry.getKey();
        List<BodyDeclaration<?>> fakeOverrideDecls = entry.getValue();
        for (BodyDeclaration<?> bodyDecl : fakeOverrideDecls) {
            processFakeOverride(fakeOverridden, (CallableDeclaration<?>) bodyDecl, typeElt);
        }
    }
    if (typeDeclTypeParameters != null) {
        typeParameters.removeAll(typeDeclTypeParameters);
    }
    return null;
}
Also used : ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) VariableElement(javax.lang.model.element.VariableElement) FieldDeclaration(com.github.javaparser.ast.body.FieldDeclaration) LinkedHashMap(java.util.LinkedHashMap) EnumConstantDeclaration(com.github.javaparser.ast.body.EnumConstantDeclaration) ArrayList(java.util.ArrayList) NodeList(com.github.javaparser.ast.NodeList) List(java.util.List) TypeElement(javax.lang.model.element.TypeElement) BugInCF(org.checkerframework.javacutil.BugInCF) EnumDeclaration(com.github.javaparser.ast.body.EnumDeclaration) RecordDeclaration(com.github.javaparser.ast.body.RecordDeclaration) AnnotationDeclaration(com.github.javaparser.ast.body.AnnotationDeclaration) ReceiverParameter(com.github.javaparser.ast.body.ReceiverParameter) Parameter(com.github.javaparser.ast.body.Parameter) TypeParameter(com.github.javaparser.ast.type.TypeParameter) BodyDeclaration(com.github.javaparser.ast.body.BodyDeclaration) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap)

Example 5 with FullyQualifiedName

use of org.checkerframework.checker.signature.qual.FullyQualifiedName in project checker-framework by typetools.

the class AnnotationFileParser method getImportedAnnotations.

/**
 * Returns all annotations imported by the annotation file, as a value for {@link
 * #allAnnotations}. Note that this also modifies {@link #importedConstants} and {@link
 * #importedTypes}.
 *
 * <p>This method misses annotations that are not imported. The {@link #getAnnotation} method
 * compensates for this deficiency by adding any fully-qualified annotation that it encounters.
 *
 * @return a map from names to TypeElement, for all annotations imported by the annotation file.
 *     Two entries for each annotation: one for the simple name and another for the
 *     fully-qualified name, with the same value.
 * @see #allAnnotations
 */
private Map<String, TypeElement> getImportedAnnotations() {
    Map<String, TypeElement> result = new HashMap<>();
    // TODO: The size can be greater than 1, but this ignores all but the first element.
    assert !stubUnit.getCompilationUnits().isEmpty();
    CompilationUnit cu = stubUnit.getCompilationUnits().get(0);
    if (cu.getImports() == null) {
        return result;
    }
    for (ImportDeclaration importDecl : cu.getImports()) {
        try {
            if (importDecl.isAsterisk()) {
                @// https://tinyurl.com/cfissue/3094:
                SuppressWarnings(// https://tinyurl.com/cfissue/3094:
                "signature") @DotSeparatedIdentifiers String imported = importDecl.getName().toString();
                if (importDecl.isStatic()) {
                    // Wildcard import of members of a type (class or interface)
                    TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
                    if (element != null) {
                        // Find nested annotations
                        // Find compile time constant fields, or values of an enum
                        putAllNew(result, annosInType(element));
                        importedConstants.addAll(getImportableMembers(element));
                        addEnclosingTypesToImportedTypes(element);
                    }
                } else {
                    // Wildcard import of members of a package
                    PackageElement element = findPackage(imported, importDecl);
                    if (element != null) {
                        putAllNew(result, annosInPackage(element));
                        addEnclosingTypesToImportedTypes(element);
                    }
                }
            } else {
                // A single (non-wildcard) import.
                @// importDecl is non-wildcard, so its name is
                SuppressWarnings(// importDecl is non-wildcard, so its name is
                "signature") @FullyQualifiedName String imported = importDecl.getNameAsString();
                final TypeElement importType = elements.getTypeElement(imported);
                if (importType == null && !importDecl.isStatic()) {
                    // Class or nested class (according to JSL), but we can't resolve
                    stubWarnNotFound(importDecl, "Imported type not found: " + imported);
                } else if (importType == null) {
                    // static import of field or method.
                    Pair<@FullyQualifiedName String, String> typeParts = AnnotationFileUtil.partitionQualifiedName(imported);
                    String type = typeParts.first;
                    String fieldName = typeParts.second;
                    TypeElement enclType = getTypeElement(type, String.format("Enclosing type of static field %s not found", fieldName), importDecl);
                    if (enclType != null) {
                        // want a warning, imported might be a method.
                        for (VariableElement field : ElementUtils.getAllFieldsIn(enclType, elements)) {
                            // field.getSimpleName() is a CharSequence, not a String
                            if (fieldName.equals(field.getSimpleName().toString())) {
                                importedConstants.add(imported);
                            }
                        }
                    }
                } else if (importType.getKind() == ElementKind.ANNOTATION_TYPE) {
                    // Single annotation or nested annotation
                    TypeElement annoElt = elements.getTypeElement(imported);
                    if (annoElt != null) {
                        putIfAbsent(result, annoElt.getSimpleName().toString(), annoElt);
                        importedTypes.put(annoElt.getSimpleName().toString(), annoElt);
                    } else {
                        stubWarnNotFound(importDecl, "Could not load import: " + imported);
                    }
                } else {
                    // Class or nested class
                    // TODO: Is this needed?
                    importedConstants.add(imported);
                    TypeElement element = getTypeElement(imported, "Imported type not found", importDecl);
                    importedTypes.put(element.getSimpleName().toString(), element);
                }
            }
        } catch (AssertionError error) {
            stubWarnNotFound(importDecl, error.toString());
        }
    }
    return result;
}
Also used : CompilationUnit(com.github.javaparser.ast.CompilationUnit) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) FullyQualifiedName(org.checkerframework.checker.signature.qual.FullyQualifiedName) VariableElement(javax.lang.model.element.VariableElement) DotSeparatedIdentifiers(org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers) ImportDeclaration(com.github.javaparser.ast.ImportDeclaration) PackageElement(javax.lang.model.element.PackageElement) Pair(org.checkerframework.javacutil.Pair) MemberValuePair(com.github.javaparser.ast.expr.MemberValuePair)

Aggregations

FullyQualifiedName (org.checkerframework.checker.signature.qual.FullyQualifiedName)9 TypeElement (javax.lang.model.element.TypeElement)7 ArrayList (java.util.ArrayList)4 VariableElement (javax.lang.model.element.VariableElement)4 HashMap (java.util.HashMap)3 PackageElement (javax.lang.model.element.PackageElement)3 BugInCF (org.checkerframework.javacutil.BugInCF)3 ImportDeclaration (com.github.javaparser.ast.ImportDeclaration)2 NodeList (com.github.javaparser.ast.NodeList)2 MemberValuePair (com.github.javaparser.ast.expr.MemberValuePair)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 DotSeparatedIdentifiers (org.checkerframework.checker.signature.qual.DotSeparatedIdentifiers)2 CompilationUnit (com.github.javaparser.ast.CompilationUnit)1 AnnotationDeclaration (com.github.javaparser.ast.body.AnnotationDeclaration)1 BodyDeclaration (com.github.javaparser.ast.body.BodyDeclaration)1 ClassOrInterfaceDeclaration (com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)1 EnumConstantDeclaration (com.github.javaparser.ast.body.EnumConstantDeclaration)1 EnumDeclaration (com.github.javaparser.ast.body.EnumDeclaration)1 FieldDeclaration (com.github.javaparser.ast.body.FieldDeclaration)1