Search in sources :

Example 16 with Pair

use of org.checkerframework.javacutil.Pair 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)

Example 17 with Pair

use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.

the class BaseTypeValidator method extractParameterizedTypeTree.

/**
 * If {@code tree} has a {@link ParameterizedTypeTree}, then the tree and its type is returned.
 * Otherwise null and {@code type} are returned.
 *
 * @param tree tree to search
 * @param type type to return if no {@code ParameterizedTypeTree} is found
 * @return if {@code tree} has a {@code ParameterizedTypeTree}, then returns the tree and its
 *     type. Otherwise, returns null and {@code type}.
 */
private Pair<@Nullable ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree(Tree tree, AnnotatedDeclaredType type) {
    ParameterizedTypeTree typeargtree = null;
    switch(tree.getKind()) {
        case VARIABLE:
            Tree lt = ((VariableTree) tree).getType();
            if (lt instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) lt;
            } else {
            // System.out.println("Found a: " + lt);
            }
            break;
        case PARAMETERIZED_TYPE:
            typeargtree = (ParameterizedTypeTree) tree;
            break;
        case NEW_CLASS:
            NewClassTree nct = (NewClassTree) tree;
            ExpressionTree nctid = nct.getIdentifier();
            if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
                typeargtree = (ParameterizedTypeTree) nctid;
                /*
           * This is quite tricky... for anonymous class instantiations,
           * the type at this point has no type arguments. By doing the
           * following, we get the type arguments again.
           */
                type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree);
            }
            break;
        case ANNOTATED_TYPE:
            AnnotatedTypeTree tr = (AnnotatedTypeTree) tree;
            ExpressionTree undtr = tr.getUnderlyingType();
            if (undtr instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) undtr;
            } else if (undtr instanceof IdentifierTree) {
            // @Something D -> Nothing to do
            } else {
                // TODO: add more test cases to ensure that nested types are
                // handled correctly,
                // e.g. @Nullable() List<@Nullable Object>[][]
                Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(undtr, type);
                typeargtree = p.first;
                type = p.second;
            }
            break;
        case IDENTIFIER:
        case ARRAY_TYPE:
        case NEW_ARRAY:
        case MEMBER_SELECT:
        case UNBOUNDED_WILDCARD:
        case EXTENDS_WILDCARD:
        case SUPER_WILDCARD:
        case TYPE_PARAMETER:
            // Nothing to do.
            break;
        case METHOD:
            // If a MethodTree is passed, it's just the return type that is validated.
            // See BaseTypeVisitor#validateTypeOf.
            MethodTree methodTree = (MethodTree) tree;
            if (methodTree.getReturnType() instanceof ParameterizedTypeTree) {
                typeargtree = (ParameterizedTypeTree) methodTree.getReturnType();
            }
            break;
        default:
            // No need to do anything further.
            break;
    }
    return Pair.of(typeargtree, type);
}
Also used : AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) IdentifierTree(com.sun.source.tree.IdentifierTree) NewClassTree(com.sun.source.tree.NewClassTree) Pair(org.checkerframework.javacutil.Pair)

Example 18 with Pair

use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.

the class MustCallConsistencyAnalyzer method getSuccessorsExceptIgnoredExceptions.

/**
 * Get all successor blocks for some block, except for those corresponding to ignored exception
 * types. See {@link #ignoredExceptionTypes}. Each exceptional successor is paired with the type
 * of exception that leads to it, for use in error messages.
 *
 * @param block input block
 * @return set of pairs (b, t), where b is a successor block, and t is the type of exception for
 *     the CFG edge from block to b, or {@code null} if b is a non-exceptional successor
 */
private Set<Pair<Block, @Nullable TypeMirror>> getSuccessorsExceptIgnoredExceptions(Block block) {
    if (block.getType() == Block.BlockType.EXCEPTION_BLOCK) {
        ExceptionBlock excBlock = (ExceptionBlock) block;
        Set<Pair<Block, @Nullable TypeMirror>> result = new LinkedHashSet<>();
        // regular successor
        Block regularSucc = excBlock.getSuccessor();
        if (regularSucc != null) {
            result.add(Pair.of(regularSucc, null));
        }
        // non-ignored exception successors
        Map<TypeMirror, Set<Block>> exceptionalSuccessors = excBlock.getExceptionalSuccessors();
        for (Map.Entry<TypeMirror, Set<Block>> entry : exceptionalSuccessors.entrySet()) {
            TypeMirror exceptionType = entry.getKey();
            if (!isIgnoredExceptionType(((Type) exceptionType).tsym.getQualifiedName())) {
                for (Block exSucc : entry.getValue()) {
                    result.add(Pair.of(exSucc, exceptionType));
                }
            }
        }
        return result;
    } else {
        Set<Pair<Block, @Nullable TypeMirror>> result = new LinkedHashSet<>();
        for (Block b : block.getSuccessors()) {
            result.add(Pair.of(b, null));
        }
        return result;
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) Block(org.checkerframework.dataflow.cfg.block.Block) SingleSuccessorBlock(org.checkerframework.dataflow.cfg.block.SingleSuccessorBlock) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) Nullable(org.checkerframework.checker.nullness.qual.Nullable) Pair(org.checkerframework.javacutil.Pair)

Example 19 with Pair

use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.

the class TreeParser method parseExpression.

/**
 * Parse an expression.
 *
 * @param tokenizer the tokenizer
 * @param token the first token
 * @return a pair of a parsed expression and the next token
 */
private Pair<JCExpression, String> parseExpression(StringTokenizer tokenizer, String token) {
    JCExpression tree = fromToken(token);
    while (tokenizer.hasMoreTokens()) {
        String delim = nextToken(tokenizer);
        token = delim;
        if (".".equals(delim)) {
            token = nextToken(tokenizer);
            tree = maker.Select(tree, names.fromString(token));
        } else if ("(".equals(delim)) {
            token = nextToken(tokenizer);
            ListBuffer<JCExpression> args = new ListBuffer<>();
            while (!")".equals(token)) {
                Pair<JCExpression, String> p = parseExpression(tokenizer, token);
                JCExpression arg = p.first;
                token = p.second;
                args.append(arg);
                if (",".equals(token)) {
                    token = nextToken(tokenizer);
                }
            }
            // For now, handle empty args only
            assert ")".equals(token) : "Unexpected token: " + token;
            tree = maker.Apply(List.nil(), tree, args.toList());
        } else if ("[".equals(token)) {
            token = nextToken(tokenizer);
            Pair<JCExpression, String> p = parseExpression(tokenizer, token);
            JCExpression index = p.first;
            token = p.second;
            assert "]".equals(token) : "Unexpected token: " + token;
            tree = maker.Indexed(tree, index);
        } else {
            return Pair.of(tree, token);
        }
        assert tokenizer != null : "@AssumeAssertion(nullness): side effects";
    }
    return Pair.of(tree, token);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) ListBuffer(com.sun.tools.javac.util.ListBuffer) Pair(org.checkerframework.javacutil.Pair)

Example 20 with Pair

use of org.checkerframework.javacutil.Pair in project checker-framework by typetools.

the class AnnotatedTypes method fixUpRawTypes.

/**
 * Some times we create type arguments for types that were raw. When we do an asSuper we lose
 * these arguments. If in the converted type (i.e. the subtype as super) is missing type arguments
 * AND those type arguments should come from the original subtype's type arguments then we copy
 * the original type arguments to the converted type. e.g. We have a type W, that "wasRaw" {@code
 * ArrayList<? extends Object>} When W is converted to type A, List, using asSuper it no longer
 * has its type argument. But since the type argument to List should be the same as that to
 * ArrayList we copy over the type argument of W to A. A becomes {@code List<? extends Object>}
 *
 * @param originalSubtype the subtype before being converted by asSuper
 * @param asSuperType he subtype after being converted by asSuper
 * @param supertype the supertype for which asSuperType should have the same underlying type
 * @param types the types utility
 */
private static void fixUpRawTypes(final AnnotatedTypeMirror originalSubtype, final AnnotatedTypeMirror asSuperType, final AnnotatedTypeMirror supertype, final Types types) {
    if (asSuperType == null || asSuperType.getKind() != TypeKind.DECLARED || originalSubtype.getKind() != TypeKind.DECLARED) {
        return;
    }
    final AnnotatedDeclaredType declaredAsSuper = (AnnotatedDeclaredType) asSuperType;
    final AnnotatedDeclaredType declaredSubtype = (AnnotatedDeclaredType) originalSubtype;
    if (!declaredAsSuper.isUnderlyingTypeRaw() || !declaredAsSuper.getTypeArguments().isEmpty() || declaredSubtype.getTypeArguments().isEmpty()) {
        return;
    }
    Set<Pair<Integer, Integer>> typeArgMap = TypeArgumentMapper.mapTypeArgumentIndices((TypeElement) declaredSubtype.getUnderlyingType().asElement(), (TypeElement) declaredAsSuper.getUnderlyingType().asElement(), types);
    if (typeArgMap.size() != declaredSubtype.getTypeArguments().size()) {
        return;
    }
    List<Pair<Integer, Integer>> orderedByDestination = new ArrayList<>(typeArgMap);
    orderedByDestination.sort(Comparator.comparingInt(o -> o.second));
    if (typeArgMap.size() == ((AnnotatedDeclaredType) supertype).getTypeArguments().size()) {
        List<? extends AnnotatedTypeMirror> subTypeArgs = declaredSubtype.getTypeArguments();
        List<AnnotatedTypeMirror> newTypeArgs = CollectionsPlume.mapList(mapping -> subTypeArgs.get(mapping.first).deepCopy(), orderedByDestination);
        declaredAsSuper.setTypeArguments(newTypeArgs);
    } else {
        declaredAsSuper.setTypeArguments(Collections.emptyList());
    }
}
Also used : AnnotatedArrayType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType) AnnotatedIntersectionType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType) BugInCF(org.checkerframework.javacutil.BugInCF) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) TypeElement(javax.lang.model.element.TypeElement) Elements(javax.lang.model.util.Elements) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) CanonicalName(org.checkerframework.checker.signature.qual.CanonicalName) Map(java.util.Map) Pair(org.checkerframework.javacutil.Pair) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) Collection(java.util.Collection) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) AnnotatedWildcardType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType) Element(javax.lang.model.element.Element) Types(javax.lang.model.util.Types) WildcardType(com.sun.tools.javac.code.Type.WildcardType) TypeKind(javax.lang.model.type.TypeKind) List(java.util.List) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) Attribute(com.sun.tools.javac.code.Attribute) TypeVariable(javax.lang.model.type.TypeVariable) TypesUtils(org.checkerframework.javacutil.TypesUtils) Type(com.sun.tools.javac.code.Type) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) HashMap(java.util.HashMap) Deque(java.util.Deque) ArrayList(java.util.ArrayList) SyntheticArrays(org.checkerframework.framework.type.SyntheticArrays) LinkedHashMap(java.util.LinkedHashMap) NewClassTree(com.sun.source.tree.NewClassTree) DeclaredType(javax.lang.model.type.DeclaredType) ElementFilter(javax.lang.model.util.ElementFilter) Tree(com.sun.source.tree.Tree) AnnotationUtils(org.checkerframework.javacutil.AnnotationUtils) LinkedHashSet(java.util.LinkedHashSet) Nullable(org.checkerframework.checker.nullness.qual.Nullable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) ExecutableElement(javax.lang.model.element.ExecutableElement) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AsSuperVisitor(org.checkerframework.framework.type.AsSuperVisitor) TypeParameterElement(javax.lang.model.element.TypeParameterElement) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) TypeMirror(javax.lang.model.type.TypeMirror) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) StringsPlume(org.plumelib.util.StringsPlume) ArrayDeque(java.util.ArrayDeque) Comparator(java.util.Comparator) Collections(java.util.Collections) ElementUtils(org.checkerframework.javacutil.ElementUtils) CollectionsPlume(org.plumelib.util.CollectionsPlume) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) ArrayList(java.util.ArrayList) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) Pair(org.checkerframework.javacutil.Pair)

Aggregations

Pair (org.checkerframework.javacutil.Pair)31 AnnotationMirror (javax.lang.model.element.AnnotationMirror)12 ArrayList (java.util.ArrayList)11 LinkedHashSet (java.util.LinkedHashSet)8 TypeElement (javax.lang.model.element.TypeElement)7 TypeMirror (javax.lang.model.type.TypeMirror)7 MethodTree (com.sun.source.tree.MethodTree)6 Tree (com.sun.source.tree.Tree)6 HashMap (java.util.HashMap)6 ExecutableElement (javax.lang.model.element.ExecutableElement)6 VariableElement (javax.lang.model.element.VariableElement)6 ClassTree (com.sun.source.tree.ClassTree)5 VariableTree (com.sun.source.tree.VariableTree)5 ExpressionTree (com.sun.source.tree.ExpressionTree)4 NewClassTree (com.sun.source.tree.NewClassTree)4 LinkedHashMap (java.util.LinkedHashMap)4 Map (java.util.Map)4 Element (javax.lang.model.element.Element)4 Nullable (org.checkerframework.checker.nullness.qual.Nullable)4 Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)4