Search in sources :

Example 1 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation in project error-prone by google.

the class ImmutableChecker method checkInvocation.

private Description checkInvocation(Tree tree, Type methodType, VisitorState state, Symbol symbol) {
    ImmutableAnalysis analysis = new ImmutableAnalysis(this, state, wellKnownMutability);
    Violation info = analysis.checkInvocation(methodType, symbol);
    if (info.isPresent()) {
        state.reportMatch(buildDescription(tree).setMessage(info.message()).build());
    }
    return NO_MATCH;
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation)

Example 2 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation in project error-prone by google.

the class ImmutableChecker method handleAnonymousClass.

// Anonymous classes
/**
 * Check anonymous implementations of {@code @Immutable} types.
 */
private Description handleAnonymousClass(ClassTree tree, VisitorState state, ImmutableAnalysis analysis) {
    ClassSymbol sym = ASTHelpers.getSymbol(tree);
    if (sym == null) {
        return NO_MATCH;
    }
    Type superType = immutableSupertype(sym, state);
    if (superType == null) {
        return NO_MATCH;
    }
    // We don't need to check that the superclass has an immutable instantiation.
    // The anonymous instance can only be referred to using a superclass type, so
    // the type arguments will be validated at any type use site where we care about
    // the instance's immutability.
    // 
    // Also, we have no way to express something like:
    // 
    // public static <@Immutable T> ImmutableBox<T> create(T t) {
    // return new ImmutableBox<>(t);
    // }
    ImmutableSet<String> typarams = immutableTypeParametersInScope(sym, state, analysis);
    Violation info = analysis.areFieldsImmutable(Optional.of(tree), typarams, ASTHelpers.getType(tree), new ViolationReporter() {

        @Override
        public Builder describe(Tree tree, Violation info) {
            return describeAnonymous(tree, superType, info);
        }
    });
    if (!info.isPresent()) {
        return NO_MATCH;
    }
    return describeAnonymous(tree, superType, info).build();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) Type(com.sun.tools.javac.code.Type) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ViolationReporter(com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.ViolationReporter) Builder(com.google.errorprone.matchers.Description.Builder) TypeParameterTree(com.sun.source.tree.TypeParameterTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) NewClassTree(com.sun.source.tree.NewClassTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree)

Example 3 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation in project error-prone by google.

the class ImmutableEnumChecker method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ClassSymbol symbol = getSymbol(tree);
    if (symbol == null || !symbol.isEnum()) {
        return NO_MATCH;
    }
    if (ASTHelpers.hasAnnotation(symbol, Immutable.class, state) && !implementsImmutableInterface(symbol)) {
        AnnotationTree annotation = ASTHelpers.getAnnotationWithSimpleName(tree.getModifiers().getAnnotations(), "Immutable");
        if (annotation != null) {
            state.reportMatch(buildDescription(annotation).setMessage(ANNOTATED_ENUM_MESSAGE).addFix(SuggestedFix.delete(annotation)).build());
        } else {
            state.reportMatch(buildDescription(tree).setMessage(ANNOTATED_ENUM_MESSAGE).build());
        }
    }
    Violation info = new ImmutableAnalysis(this, state, wellKnownMutability, ImmutableSet.of(Immutable.class.getName(), javax.annotation.concurrent.Immutable.class.getName())).checkForImmutability(Optional.of(tree), ImmutableSet.of(), getType(tree), this::describe);
    if (!info.isPresent()) {
        return NO_MATCH;
    }
    return describe(tree, info).build();
}
Also used : Immutable(com.google.errorprone.annotations.Immutable) Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) AnnotationTree(com.sun.source.tree.AnnotationTree)

Example 4 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation 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 Violation

use of com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation in project error-prone by google.

the class ImmutableAnalysis method checkSuper.

private Violation checkSuper(ImmutableSet<String> immutableTyParams, ClassType type) {
    ClassType superType = (ClassType) state.getTypes().supertype(type);
    if (superType.getKind() == TypeKind.NONE || state.getTypes().isSameType(state.getSymtab().objectType, superType)) {
        return Violation.absent();
    }
    if (WellKnownMutability.isAnnotation(state, type)) {
        // TODO(b/25630189): add enforcement
        return Violation.absent();
    }
    AnnotationInfo superannotation = getImmutableAnnotation(superType.tsym, state);
    String message = String.format("'%s' extends '%s'", threadSafety.getPrettyName(type.tsym), threadSafety.getPrettyName(superType.tsym));
    if (superannotation != null) {
        // If the superclass does happen to be immutable, we don't need to recursively
        // inspect it. We just have to check that it's instantiated correctly:
        Violation info = threadSafety.checkSuperInstantiation(immutableTyParams, superannotation, superType);
        if (!info.isPresent()) {
            return Violation.absent();
        }
        return info.plus(message);
    }
    // Recursive case: check if the supertype is 'effectively' immutable.
    Violation info = checkForImmutability(Optional.<ClassTree>empty(), immutableTyParams, superType, new ViolationReporter() {

        @Override
        public Description.Builder describe(Tree tree, Violation info) {
            return BugChecker.buildDescriptionFromChecker(tree, bugChecker).setMessage(info.plus(info.message()).message());
        }
    });
    if (!info.isPresent()) {
        return Violation.absent();
    }
    return info.plus(message);
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ClassType(com.sun.tools.javac.code.Type.ClassType)

Aggregations

Violation (com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation)11 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)6 ClassTree (com.sun.source.tree.ClassTree)5 Tree (com.sun.source.tree.Tree)4 Type (com.sun.tools.javac.code.Type)4 ClassType (com.sun.tools.javac.code.Type.ClassType)4 TypeVariableSymbol (com.sun.tools.javac.code.Symbol.TypeVariableSymbol)3 Immutable (com.google.errorprone.annotations.Immutable)2 AnnotationTree (com.sun.source.tree.AnnotationTree)2 MemberReferenceTree (com.sun.source.tree.MemberReferenceTree)2 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)2 NewClassTree (com.sun.source.tree.NewClassTree)2 TypeParameterTree (com.sun.source.tree.TypeParameterTree)2 Symbol (com.sun.tools.javac.code.Symbol)2 HashMap (java.util.HashMap)2 AutoValue (com.google.auto.value.AutoValue)1 Joiner (com.google.common.base.Joiner)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 ImmutableList (com.google.common.collect.ImmutableList)1