Search in sources :

Example 6 with TypeVariableSymbol

use of com.sun.tools.javac.code.Symbol.TypeVariableSymbol in project error-prone by google.

the class FutureReturnValueIgnored method checkLostType.

private Description checkLostType(MethodInvocationTree tree, VisitorState state) {
    Type futureType = Objects.requireNonNull(state.getTypeFromString("java.util.concurrent.Future"));
    MethodSymbol sym = ASTHelpers.getSymbol(tree);
    Type returnType = ASTHelpers.getResultType(tree);
    Type returnedFutureType = state.getTypes().asSuper(returnType, futureType.tsym);
    if (returnedFutureType != null && !returnedFutureType.isRaw()) {
        if (ASTHelpers.isSubtype(ASTHelpers.getUpperBound(returnedFutureType.getTypeArguments().get(0), state.getTypes()), futureType, state)) {
            return buildDescription(tree).setMessage(String.format("Method returns a nested type, %s", returnType)).build();
        }
        // The type variable that determines the generic on the returned future was not a Future.
        // However, many methods (like guava's Futures.transform) have signatures like this:
        // Future<O> do(SomeObject<? extends O>). If O resolves to java.lang.Object or ?, then a
        // SomeObject<Future> is a valid parameter to pass, but results in a nested future.
        Type methodReturnType = sym.getReturnType();
        List<TypeVariableSymbol> typeParameters = sym.getTypeParameters();
        Set<TypeVariableSymbol> returnTypeChoosing = new HashSet<>();
        // of Future, that means that a nested Future is being returned.
        for (TypeVariableSymbol tvs : typeParameters) {
            Queue<TypeVariableSymbol> queue = new ArrayDeque<>();
            queue.add(tvs);
            while (!queue.isEmpty()) {
                TypeVariableSymbol currentTypeParam = queue.poll();
                for (Type typeParam : methodReturnType.getTypeArguments()) {
                    if (typeParam.tsym == currentTypeParam) {
                        returnTypeChoosing.add(tvs);
                    }
                }
                for (Type toAdd : currentTypeParam.getBounds()) {
                    if (toAdd.tsym instanceof TypeVariableSymbol) {
                        queue.add((TypeVariableSymbol) toAdd.tsym);
                    }
                }
            }
        }
        // of Future.
        if (!returnTypeChoosing.isEmpty()) {
            Multimap<TypeVariableSymbol, TypeInfo> resolved = getResolvedGenerics(tree);
            for (TypeVariableSymbol returnTypeChoosingSymbol : returnTypeChoosing) {
                Collection<TypeInfo> types = resolved.get(returnTypeChoosingSymbol);
                for (TypeInfo type : types) {
                    if (ASTHelpers.isSubtype(type.resolvedVariableType, futureType, state)) {
                        return buildDescription(type.tree).setMessage(String.format("Invocation produces a nested type - Type variable %s, as part of return " + "type %s resolved to %s.", returnTypeChoosingSymbol, methodReturnType, type.resolvedVariableType)).build();
                    }
                }
            }
        }
    }
    if (allOf(allOf(parentNode(FutureReturnValueIgnored::isObjectReturningLambdaExpression), not(AbstractReturnValueIgnored::expectedExceptionTest)), specializedMatcher(), not((t, s) -> ASTHelpers.isVoidType(ASTHelpers.getType(t), s))).matches(tree, state)) {
        return describe(tree, state);
    }
    return Description.NO_MATCH;
}
Also used : Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) ArrayDeque(java.util.ArrayDeque) HashSet(java.util.HashSet)

Example 7 with TypeVariableSymbol

use of com.sun.tools.javac.code.Symbol.TypeVariableSymbol in project error-prone by google.

the class FutureReturnValueIgnored method getResolvedGenerics.

private static Multimap<TypeVariableSymbol, TypeInfo> getResolvedGenerics(MethodInvocationTree tree) {
    Type type = ASTHelpers.getType(tree.getMethodSelect());
    List<Type> from = new ArrayList<>();
    List<Type> to = new ArrayList<>();
    getSubst(type, from, to);
    Multimap<TypeVariableSymbol, TypeInfo> result = Streams.zip(from.stream(), to.stream(), (f, t) -> new TypeInfo((TypeVariableSymbol) f.asElement(), t, tree)).collect(toMultimap(k -> k.sym, k -> k, MultimapBuilder.linkedHashKeys().arrayListValues()::build));
    return result;
}
Also used : Matchers.anyOf(com.google.errorprone.matchers.Matchers.anyOf) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MultimapBuilder(com.google.common.collect.MultimapBuilder) Matchers.parentNode(com.google.errorprone.matchers.Matchers.parentNode) CompletionService(java.util.concurrent.CompletionService) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) JCMemberReference(com.sun.tools.javac.tree.JCTree.JCMemberReference) Matchers.allOf(com.google.errorprone.matchers.Matchers.allOf) StandardTags(com.google.errorprone.BugPattern.StandardTags) Matcher(com.google.errorprone.matchers.Matcher) ReferenceMode(com.sun.source.tree.MemberReferenceTree.ReferenceMode) ImmutableSet(com.google.common.collect.ImmutableSet) Collection(java.util.Collection) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) CanIgnoreReturnValue(com.google.errorprone.annotations.CanIgnoreReturnValue) Streams(com.google.common.collect.Streams) TypeKind(javax.lang.model.type.TypeKind) Objects(java.util.Objects) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) List(java.util.List) Description(com.google.errorprone.matchers.Description) JCLambda(com.sun.tools.javac.tree.JCTree.JCLambda) Queue(java.util.Queue) Pattern(java.util.regex.Pattern) Type(com.sun.tools.javac.code.Type) ReturnTree(com.sun.source.tree.ReturnTree) MethodTree(com.sun.source.tree.MethodTree) ReturnTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ReturnTreeMatcher) MethodMatchers.instanceMethod(com.google.errorprone.matchers.method.MethodMatchers.instanceMethod) Multimap(com.google.common.collect.Multimap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) VisitorState(com.google.errorprone.VisitorState) Multimaps.toMultimap(com.google.common.collect.Multimaps.toMultimap) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Tree(com.sun.source.tree.Tree) ASTHelpers.hasAnnotation(com.google.errorprone.util.ASTHelpers.hasAnnotation) Matchers.not(com.google.errorprone.matchers.Matchers.not) ForkJoinTask(java.util.concurrent.ForkJoinTask) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) Field(java.lang.reflect.Field) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) InvocationHandler(java.lang.reflect.InvocationHandler) ArrayDeque(java.util.ArrayDeque) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) ArrayList(java.util.ArrayList) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol)

Example 8 with TypeVariableSymbol

use of com.sun.tools.javac.code.Symbol.TypeVariableSymbol in project error-prone by google.

the class TypeParameterShadowing method renameTypeVariable.

static SuggestedFix renameTypeVariable(TypeParameterTree typeParameter, Tree owningTree, String typeVarReplacement, VisitorState state) {
    Symbol typeVariableSymbol = ASTHelpers.getSymbol(typeParameter);
    // replace only the type parameter name (and not any upper bounds)
    String name = typeParameter.getName().toString();
    int pos = ((JCTree) typeParameter).getStartPosition();
    SuggestedFix.Builder fixBuilder = SuggestedFix.builder().replace(pos, pos + name.length(), typeVarReplacement);
    ((JCTree) owningTree).accept(new TreeScanner() {

        @Override
        public void visitIdent(JCTree.JCIdent tree) {
            Symbol identSym = ASTHelpers.getSymbol(tree);
            if (Objects.equal(identSym, typeVariableSymbol)) {
                // }
                if (Objects.equal(state.getSourceForNode(tree), name)) {
                    fixBuilder.replace(tree, typeVarReplacement);
                }
            }
        }
    });
    return fixBuilder.build();
}
Also used : SuggestedFix(com.google.errorprone.fixes.SuggestedFix) TreeScanner(com.sun.tools.javac.tree.TreeScanner) Symbol(com.sun.tools.javac.code.Symbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) JCTree(com.sun.tools.javac.tree.JCTree)

Example 9 with TypeVariableSymbol

use of com.sun.tools.javac.code.Symbol.TypeVariableSymbol in project checker-framework by typetools.

the class TypeFromTypeTreeVisitor method updateWildcardBounds.

/**
 * Work around a bug in javac 9 where sometimes the bound field is set to the transitive
 * supertype's type parameter instead of the type parameter which the wildcard directly
 * instantiates. See https://github.com/eisop/checker-framework/issues/18
 *
 * <p>Sets each wildcard type argument's bound from typeArgs to the corresponding type parameter
 * from typeParams.
 *
 * <p>If typeArgs.size() == 0 the method does nothing and returns. Otherwise, typeArgs.size() has
 * to be equal to typeParams.size().
 *
 * <p>For each wildcard type argument and corresponding type parameter, sets the
 * WildcardType.bound field to the corresponding type parameter, if and only if the owners of the
 * existing bound and the type parameter are different.
 *
 * <p>In scenarios where the bound's owner is the same, we don't want to replace a
 * capture-converted bound in the wildcard type with a non-capture-converted bound given by the
 * type parameter declaration.
 *
 * @param typeArgs the type of the arguments at (e.g., at the call side)
 * @param typeParams the type of the formal parameters (e.g., at the method declaration)
 */
// workaround for javac bug
@SuppressWarnings("interning:not.interned")
private void updateWildcardBounds(List<? extends Tree> typeArgs, List<TypeVariableSymbol> typeParams) {
    if (typeArgs.isEmpty()) {
        // Nothing to do for empty type arguments.
        return;
    }
    assert typeArgs.size() == typeParams.size();
    Iterator<? extends Tree> typeArgsItr = typeArgs.iterator();
    Iterator<TypeVariableSymbol> typeParamsItr = typeParams.iterator();
    while (typeArgsItr.hasNext()) {
        Tree typeArg = typeArgsItr.next();
        TypeVariableSymbol typeParam = typeParamsItr.next();
        if (typeArg instanceof WildcardTree) {
            TypeVar typeVar = (TypeVar) typeParam.asType();
            WildcardType wcType = (WildcardType) ((JCWildcard) typeArg).type;
            if (wcType.bound != null && wcType.bound.tsym != null && typeVar.tsym != null && wcType.bound.tsym.owner != typeVar.tsym.owner) {
                wcType.withTypeVar(typeVar);
            }
        }
    }
}
Also used : TypeVar(com.sun.tools.javac.code.Type.TypeVar) AnnotatedWildcardType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) MethodTree(com.sun.source.tree.MethodTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) TypeParameterTree(com.sun.source.tree.TypeParameterTree) 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) MemberSelectTree(com.sun.source.tree.MemberSelectTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) IntersectionTypeTree(com.sun.source.tree.IntersectionTypeTree) WildcardTree(com.sun.source.tree.WildcardTree) UnionTypeTree(com.sun.source.tree.UnionTypeTree) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) WildcardTree(com.sun.source.tree.WildcardTree)

Example 10 with TypeVariableSymbol

use of com.sun.tools.javac.code.Symbol.TypeVariableSymbol in project error-prone by google.

the class ImmutableAnalysis method immutableInstantiation.

/**
   * Check that a type-use of an {@code @Immutable}-annotated type is instantiated with immutable
   * type arguments where required by its annotation's containerOf element.
   *
   * @param immutableTyParams the in-scope immutable type parameters, declared on some enclosing
   *     class.
   * @param annotation the type's {@code @Immutable} info
   * @param type the type to check
   */
Violation immutableInstantiation(ImmutableSet<String> immutableTyParams, ImmutableAnnotationInfo annotation, Type type) {
    if (!annotation.containerOf().isEmpty() && type.tsym.getTypeParameters().size() != type.getTypeArguments().size()) {
        return Violation.of(String.format("'%s' required immutable instantiation of '%s', but was raw", getPrettyName(type.tsym), Joiner.on(", ").join(annotation.containerOf())));
    }
    for (int i = 0; i < type.tsym.getTypeParameters().size(); i++) {
        TypeVariableSymbol typaram = type.tsym.getTypeParameters().get(i);
        if (annotation.containerOf().contains(typaram.getSimpleName().toString())) {
            Type tyarg = type.getTypeArguments().get(i);
            Violation info = isImmutableType(immutableTyParams, tyarg);
            if (info.isPresent()) {
                return info.plus(String.format("'%s' was instantiated with mutable type for '%s'", getPrettyName(type.tsym), typaram.getSimpleName()));
            }
        }
    }
    return Violation.absent();
}
Also used : ClassType(com.sun.tools.javac.code.Type.ClassType) ArrayType(com.sun.tools.javac.code.Type.ArrayType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Type(com.sun.tools.javac.code.Type) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol)

Aggregations

TypeVariableSymbol (com.sun.tools.javac.code.Symbol.TypeVariableSymbol)13 Symbol (com.sun.tools.javac.code.Symbol)7 ClassTree (com.sun.source.tree.ClassTree)6 ArrayList (java.util.ArrayList)6 Streams (com.google.common.collect.Streams)5 VisitorState (com.google.errorprone.VisitorState)5 ASTHelpers (com.google.errorprone.util.ASTHelpers)5 MethodTree (com.sun.source.tree.MethodTree)5 Tree (com.sun.source.tree.Tree)5 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)5 Type (com.sun.tools.javac.code.Type)5 List (java.util.List)5 Set (java.util.Set)5 TypeParameterTree (com.sun.source.tree.TypeParameterTree)4 TypeVar (com.sun.tools.javac.code.Type.TypeVar)4 WildcardType (com.sun.tools.javac.code.Type.WildcardType)4 ImmutableSet (com.google.common.collect.ImmutableSet)3 BugPattern (com.google.errorprone.BugPattern)3 JDK (com.google.errorprone.BugPattern.Category.JDK)3 WARNING (com.google.errorprone.BugPattern.SeverityLevel.WARNING)3