Search in sources :

Example 6 with Violation

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

the class ImmutableAnalysis method areFieldsImmutable.

/**
 * Check a single class' fields for immutability.
 *
 * @param immutableTyParams the in-scope immutable type parameters
 * @param classType the type to check the fields of
 */
Violation areFieldsImmutable(Optional<ClassTree> tree, ImmutableSet<String> immutableTyParams, ClassType classType, ViolationReporter reporter) {
    ClassSymbol classSym = (ClassSymbol) classType.tsym;
    if (classSym.members() == null) {
        return Violation.absent();
    }
    Filter<Symbol> instanceFieldFilter = new Filter<Symbol>() {

        @Override
        public boolean accepts(Symbol symbol) {
            return symbol.getKind() == ElementKind.FIELD && !symbol.isStatic();
        }
    };
    Map<Symbol, Tree> declarations = new HashMap<>();
    if (tree.isPresent()) {
        for (Tree member : tree.get().getMembers()) {
            Symbol sym = ASTHelpers.getSymbol(member);
            if (sym != null) {
                declarations.put(sym, member);
            }
        }
    }
    // javac gives us members in reverse declaration order
    // handling them in declaration order leads to marginally better diagnostics
    List<Symbol> members = ImmutableList.copyOf(classSym.members().getSymbols(instanceFieldFilter)).reverse();
    for (Symbol member : members) {
        Optional<Tree> memberTree = Optional.ofNullable(declarations.get(member));
        Violation info = isFieldImmutable(memberTree, immutableTyParams, classSym, classType, (VarSymbol) member, reporter);
        if (info.isPresent()) {
            return info;
        }
    }
    return Violation.absent();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) Filter(com.sun.tools.javac.util.Filter) HashMap(java.util.HashMap) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree)

Example 7 with Violation

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

the class ImmutableAnalysis method checkForImmutability.

/**
 * Check that an {@code @Immutable}-annotated class:
 *
 * <ul>
 *   <li>does not declare or inherit any mutable fields,
 *   <li>any immutable supertypes are instantiated with immutable type arguments as required by
 *       their containerOf spec, and
 *   <li>any enclosing instances are immutable.
 * </ul>
 *
 * requiring supertypes to be annotated immutable would be too restrictive.
 */
public Violation checkForImmutability(Optional<ClassTree> tree, ImmutableSet<String> immutableTyParams, ClassType type, ViolationReporter reporter) {
    Violation info = areFieldsImmutable(tree, immutableTyParams, type, reporter);
    if (info.isPresent()) {
        return info;
    }
    for (Type interfaceType : state.getTypes().interfaces(type)) {
        AnnotationInfo interfaceAnnotation = getImmutableAnnotation(interfaceType.tsym, state);
        if (interfaceAnnotation == null) {
            continue;
        }
        info = threadSafety.checkSuperInstantiation(immutableTyParams, interfaceAnnotation, interfaceType);
        if (info.isPresent()) {
            return info.plus(String.format("'%s' extends '%s'", threadSafety.getPrettyName(type.tsym), threadSafety.getPrettyName(interfaceType.tsym)));
        }
    }
    if (!type.asElement().isEnum()) {
        // don't check enum super types here to avoid double-reporting errors
        info = checkSuper(immutableTyParams, type);
        if (info.isPresent()) {
            return info;
        }
    }
    Type mutableEnclosing = threadSafety.mutableEnclosingInstance(tree, type);
    if (mutableEnclosing != null) {
        return info.plus(String.format("'%s' has mutable enclosing instance '%s'", threadSafety.getPrettyName(type.tsym), mutableEnclosing));
    }
    return Violation.absent();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type)

Example 8 with Violation

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

the class ImmutableAnalysis method isFieldImmutable.

/**
 * Check a single field for immutability.
 */
private Violation isFieldImmutable(Optional<Tree> tree, ImmutableSet<String> immutableTyParams, ClassSymbol classSym, ClassType classType, VarSymbol var, ViolationReporter reporter) {
    if (bugChecker.isSuppressed(var)) {
        return Violation.absent();
    }
    if (!var.getModifiers().contains(Modifier.FINAL) && !ASTHelpers.hasAnnotation(var, LazyInit.class, state)) {
        Violation info = Violation.of(String.format("'%s' has non-final field '%s'", threadSafety.getPrettyName(classSym), var.getSimpleName()));
        if (tree.isPresent()) {
            // If we have a tree to attach diagnostics to, report the error immediately instead of
            // accumulating the path to the error from the top-level class being checked
            state.reportMatch(reporter.report(tree.get(), info, SuggestedFixes.addModifiers(tree.get(), state, Modifier.FINAL)));
            return Violation.absent();
        }
        return info;
    }
    Type varType = state.getTypes().memberType(classType, var);
    Violation info = threadSafety.isThreadSafeType(/* allowContainerTypeParameters= */
    true, immutableTyParams, varType);
    if (info.isPresent()) {
        info = info.plus(String.format("'%s' has field '%s' of type '%s'", threadSafety.getPrettyName(classSym), var.getSimpleName(), varType));
        if (tree.isPresent()) {
            // If we have a tree to attach diagnostics to, report the error immediately instead of
            // accumulating the path to the error from the top-level class being checked
            state.reportMatch(reporter.report(tree.get(), info, Optional.empty()));
            return Violation.absent();
        }
        return info;
    }
    return Violation.absent();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type)

Example 9 with Violation

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

the class ImmutableAnnotationChecker method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ClassSymbol symbol = getSymbol(tree);
    if (symbol == null || symbol.isAnnotationType() || !WellKnownMutability.isAnnotation(state, symbol.type)) {
        return NO_MATCH;
    }
    if (!Collections.disjoint(getGeneratedBy(symbol, state), PROCESSOR_BLACKLIST)) {
        return NO_MATCH;
    }
    if (ASTHelpers.hasAnnotation(symbol, Immutable.class, state)) {
        AnnotationTree annotation = ASTHelpers.getAnnotationWithSimpleName(tree.getModifiers().getAnnotations(), "Immutable");
        if (annotation != null) {
            state.reportMatch(buildDescription(annotation).setMessage(ANNOTATED_ANNOTATION_MESSAGE).addFix(SuggestedFix.delete(annotation)).build());
        } else {
            state.reportMatch(buildDescription(tree).setMessage(ANNOTATED_ANNOTATION_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::describeClass);
    if (!info.isPresent()) {
        return NO_MATCH;
    }
    return describeClass(tree, info).build();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation) Immutable(com.google.errorprone.annotations.Immutable) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) AnnotationTree(com.sun.source.tree.AnnotationTree)

Example 10 with Violation

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

the class ImmutableChecker method matchNewClass.

@Override
public Description matchNewClass(NewClassTree tree, VisitorState state) {
    // check instantiations of `@ImmutableTypeParameter`s in generic constructor invocations
    checkInvocation(tree, ((JCNewClass) tree).constructorType, state, ((JCNewClass) tree).constructor);
    // check instantiations of `@ImmutableTypeParameter`s in class constructor invocations
    ImmutableAnalysis analysis = new ImmutableAnalysis(this, state, wellKnownMutability);
    Violation info = analysis.checkInstantiation(ASTHelpers.getSymbol(tree.getIdentifier()).getTypeParameters(), ASTHelpers.getType(tree).getTypeArguments());
    if (info.isPresent()) {
        state.reportMatch(buildDescription(tree).setMessage(info.message()).build());
    }
    return NO_MATCH;
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ThreadSafety.Violation)

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