Search in sources :

Example 1 with TypeVariableSymbol

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

the class TypeParameterShadowing method renameTypeVariable.

private static SuggestedFix renameTypeVariable(Tree sourceTree, List<? extends TypeParameterTree> typeParameters, Name typeVariable, String typeVarReplacement, VisitorState state) {
    TypeParameterTree matchingTypeParam = typeParameters.stream().filter(t -> t.getName().contentEquals(typeVariable)).collect(MoreCollectors.onlyElement());
    Symbol typeVariableSymbol = ASTHelpers.getSymbol(matchingTypeParam);
    // replace only the type parameter name (and not any upper bounds)
    String name = matchingTypeParam.getName().toString();
    int pos = ((JCTree) matchingTypeParam).getStartPosition();
    SuggestedFix.Builder fixBuilder = SuggestedFix.builder().replace(pos, pos + name.length(), typeVarReplacement);
    ((JCTree) sourceTree).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 : ClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher) MethodTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher) MethodTree(com.sun.source.tree.MethodTree) TreeScanner(com.sun.tools.javac.tree.TreeScanner) TypeParameterTree(com.sun.source.tree.TypeParameterTree) ArrayList(java.util.ArrayList) VisitorState(com.google.errorprone.VisitorState) Matcher(java.util.regex.Matcher) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Objects(com.google.common.base.Objects) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) Name(javax.lang.model.element.Name) MoreCollectors(com.google.common.collect.MoreCollectors) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Streams(com.google.common.collect.Streams) JCTree(com.sun.tools.javac.tree.JCTree) Collectors(java.util.stream.Collectors) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) List(java.util.List) Description(com.google.errorprone.matchers.Description) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Pattern(java.util.regex.Pattern) ASTHelpers(com.google.errorprone.util.ASTHelpers) TypeParameterTree(com.sun.source.tree.TypeParameterTree) 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 2 with TypeVariableSymbol

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

the class ImmutableChecker method matchTypeParameter.

@Override
public Description matchTypeParameter(TypeParameterTree tree, VisitorState state) {
    Symbol sym = ASTHelpers.getSymbol(tree);
    if (sym == null) {
        return NO_MATCH;
    }
    ImmutableAnalysis analysis = new ImmutableAnalysis(this, state, wellKnownMutability);
    if (!analysis.isImmutableTypeParameter((TypeVariableSymbol) sym)) {
        return NO_MATCH;
    }
    switch(sym.owner.getKind()) {
        case METHOD:
        case CONSTRUCTOR:
            return NO_MATCH;
        // fall out
        default:
    }
    AnnotationInfo info = analysis.getImmutableAnnotation(sym.owner, state);
    if (info == null) {
        return buildDescription(tree).setMessage("@Immutable is only supported on immutable classes").build();
    }
    return NO_MATCH;
}
Also used : ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol)

Example 3 with TypeVariableSymbol

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

the class ThreadSafety method getAnnotation.

private AnnotationInfo getAnnotation(Symbol sym, VisitorState state, String annotation, @Nullable Class<? extends Annotation> elementAnnotation) {
    if (sym == null) {
        return null;
    }
    Symbol annosym = state.getSymbolFromString(annotation);
    Optional<Compound> attr = sym.getAnnotationMirrors().stream().filter(a -> a.getAnnotationType().asElement().equals(annosym)).findAny();
    if (attr.isPresent()) {
        ImmutableList<String> containerElements = containerOf(state, attr.get());
        if (elementAnnotation != null && containerElements.isEmpty()) {
            containerElements = sym.getTypeParameters().stream().filter(p -> p.getAnnotation(elementAnnotation) != null).map(p -> p.getSimpleName().toString()).collect(toImmutableList());
        }
        return AnnotationInfo.create(sym.getQualifiedName().toString(), containerElements);
    }
    // @ThreadSafe is inherited from supertypes
    if (!(sym instanceof ClassSymbol)) {
        return null;
    }
    Type superClass = ((ClassSymbol) sym).getSuperclass();
    AnnotationInfo superAnnotation = getInheritedAnnotation(superClass.asElement(), state);
    if (superAnnotation == null) {
        return null;
    }
    // If an annotated super-type was found, look for any type arguments to the super-type that
    // are in the super-type's containerOf spec, and where the arguments are type parameters
    // of the current class.
    // E.g. for `Foo<X> extends Super<X>` if `Super<Y>` is annotated
    // `@ThreadSafeContainerAnnotation Y`
    // then `Foo<X>` is has X implicitly annotated `@ThreadSafeContainerAnnotation X`
    ImmutableList.Builder<String> containerOf = ImmutableList.builder();
    for (int i = 0; i < superClass.getTypeArguments().size(); i++) {
        Type arg = superClass.getTypeArguments().get(i);
        TypeVariableSymbol formal = superClass.asElement().getTypeParameters().get(i);
        if (!arg.hasTag(TypeTag.TYPEVAR)) {
            continue;
        }
        TypeSymbol argSym = arg.asElement();
        if (argSym.owner == sym && superAnnotation.containerOf().contains(formal.getSimpleName().toString())) {
            containerOf.add(argSym.getSimpleName().toString());
        }
    }
    return AnnotationInfo.create(superAnnotation.typeName(), containerOf.build());
}
Also used : Iterables(com.google.common.collect.Iterables) Arrays(java.util.Arrays) ClassType(com.sun.tools.javac.code.Type.ClassType) ArrayType(com.sun.tools.javac.code.Type.ArrayType) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeVar(com.sun.tools.javac.code.Type.TypeVar) ArrayList(java.util.ArrayList) VisitorState(com.google.errorprone.VisitorState) ConsPStack(org.pcollections.ConsPStack) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) ImmutableList(com.google.common.collect.ImmutableList) TypeTag(com.sun.tools.javac.code.TypeTag) Map(java.util.Map) ClassTree(com.sun.source.tree.ClassTree) Nullable(javax.annotation.Nullable) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) SimpleAnnotationValueVisitor8(javax.lang.model.util.SimpleAnnotationValueVisitor8) ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Collection(java.util.Collection) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Compound(com.sun.tools.javac.code.Attribute.Compound) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Target(java.lang.annotation.Target) Streams(com.google.common.collect.Streams) ElementType(java.lang.annotation.ElementType) Field(java.lang.reflect.Field) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) CanBeStaticAnalyzer(com.google.errorprone.bugpatterns.CanBeStaticAnalyzer) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) List(java.util.List) Types(com.sun.tools.javac.code.Types) Attribute(com.sun.tools.javac.code.Attribute) AutoValue(com.google.auto.value.AutoValue) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) AnnotationValue(javax.lang.model.element.AnnotationValue) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Joiner(com.google.common.base.Joiner) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ImmutableList(com.google.common.collect.ImmutableList) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Compound(com.sun.tools.javac.code.Attribute.Compound) ClassType(com.sun.tools.javac.code.Type.ClassType) ArrayType(com.sun.tools.javac.code.Type.ArrayType) ElementType(java.lang.annotation.ElementType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Type(com.sun.tools.javac.code.Type) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol)

Example 4 with TypeVariableSymbol

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

the class ThreadSafety method threadSafeInstantiation.

/**
 * Check that a type-use of an {@code @ThreadSafe}-annotated type is instantiated with threadsafe
 * type arguments where required by its annotation's containerOf element.
 *
 * @param containerTypeParameters the in-scope threadsafe type parameters, declared on some
 *     enclosing class.
 * @param annotation the type's {@code @ThreadSafe} info
 * @param type the type to check
 */
public Violation threadSafeInstantiation(Set<String> containerTypeParameters, AnnotationInfo annotation, Type type) {
    if (!annotation.containerOf().isEmpty() && type.tsym.getTypeParameters().size() != type.getTypeArguments().size()) {
        return Violation.of(String.format("'%s' required instantiation of '%s' with type parameters, 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);
        boolean immutableTypeParameter = isThreadSafeTypeParameter(typaram);
        if (annotation.containerOf().contains(typaram.getSimpleName().toString()) || immutableTypeParameter) {
            Type tyarg = type.getTypeArguments().get(i);
            if (suppressAnnotation != null && tyarg.getAnnotationMirrors().stream().anyMatch(a -> ((ClassSymbol) a.getAnnotationType().asElement()).flatName().contentEquals(suppressAnnotation.getName()))) {
                continue;
            }
            Violation info = isThreadSafeType(!immutableTypeParameter, containerTypeParameters, 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 : Iterables(com.google.common.collect.Iterables) Arrays(java.util.Arrays) ClassType(com.sun.tools.javac.code.Type.ClassType) ArrayType(com.sun.tools.javac.code.Type.ArrayType) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeVar(com.sun.tools.javac.code.Type.TypeVar) ArrayList(java.util.ArrayList) VisitorState(com.google.errorprone.VisitorState) ConsPStack(org.pcollections.ConsPStack) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) ImmutableList(com.google.common.collect.ImmutableList) TypeTag(com.sun.tools.javac.code.TypeTag) Map(java.util.Map) ClassTree(com.sun.source.tree.ClassTree) Nullable(javax.annotation.Nullable) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) SimpleAnnotationValueVisitor8(javax.lang.model.util.SimpleAnnotationValueVisitor8) ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Collection(java.util.Collection) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Compound(com.sun.tools.javac.code.Attribute.Compound) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Target(java.lang.annotation.Target) Streams(com.google.common.collect.Streams) ElementType(java.lang.annotation.ElementType) Field(java.lang.reflect.Field) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) CanBeStaticAnalyzer(com.google.errorprone.bugpatterns.CanBeStaticAnalyzer) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) List(java.util.List) Types(com.sun.tools.javac.code.Types) Attribute(com.sun.tools.javac.code.Attribute) AutoValue(com.google.auto.value.AutoValue) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) AnnotationValue(javax.lang.model.element.AnnotationValue) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Joiner(com.google.common.base.Joiner) Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) ClassType(com.sun.tools.javac.code.Type.ClassType) ArrayType(com.sun.tools.javac.code.Type.ArrayType) ElementType(java.lang.annotation.ElementType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Type(com.sun.tools.javac.code.Type) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol)

Example 5 with TypeVariableSymbol

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

the class CompatibleWithMisuse method matchAnnotation.

@Override
public Description matchAnnotation(AnnotationTree annoTree, VisitorState state) {
    if (!IS_COMPATIBLE_WITH_ANNOTATION.matches(annoTree, state)) {
        return Description.NO_MATCH;
    }
    // Hunt for type args on the declared method
    // TODO(glorioso): Once annotation is TYPE_USE, make sure that the node is actually a method
    // parameter
    MethodTree methodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class);
    MethodSymbol declaredMethod = ASTHelpers.getSymbol(methodTree);
    // This restriction may need to be removed to allow more complex declaration hierarchies.
    for (MethodSymbol methodSymbol : ASTHelpers.findSuperMethods(declaredMethod, state.getTypes())) {
        if (methodSymbol.params().stream().anyMatch(p -> ASTHelpers.hasAnnotation(p, CompatibleWith.class, state))) {
            return describeWithMessage(annoTree, String.format("This method overrides a method in %s that already has @CompatibleWith", methodSymbol.owner.getSimpleName()));
        }
    }
    List<TypeVariableSymbol> potentialTypeVars = new ArrayList<>(declaredMethod.getTypeParameters());
    // Check enclosing types (not superclasses)
    ClassSymbol cs = (ClassSymbol) declaredMethod.owner;
    do {
        potentialTypeVars.addAll(cs.getTypeParameters());
        cs = cs.isInner() ? cs.owner.enclClass() : null;
    } while (cs != null);
    if (potentialTypeVars.isEmpty()) {
        return describeWithMessage(annoTree, "There are no type arguments in scope to match against.");
    }
    Set<String> validNames = potentialTypeVars.stream().map(TypeVariableSymbol::getSimpleName).map(Object::toString).collect(toImmutableSet());
    String constValue = valueArgumentFromCompatibleWithAnnotation(annoTree);
    if (constValue == null || constValue.isEmpty()) {
        return describeWithMessage(annoTree, String.format("The value of @CompatibleWith must not be empty (valid arguments are %s)", printTypeArgs(validNames)));
    }
    return validNames.contains(constValue) ? Description.NO_MATCH : describeWithMessage(annoTree, String.format("%s is not a valid type argument. Valid arguments are: %s", constValue, printTypeArgs(validNames)));
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ArrayList(java.util.ArrayList) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) CompatibleWith(com.google.errorprone.annotations.CompatibleWith)

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