Search in sources :

Example 1 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.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 Description.NO_MATCH;
    }
    Type superType = immutableSupertype(sym, state);
    if (superType == null) {
        return Description.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);
    Violation info = analysis.areFieldsImmutable(Optional.of(tree), typarams, ASTHelpers.getType(tree));
    if (!info.isPresent()) {
        return Description.NO_MATCH;
    }
    String reason = Joiner.on(", ").join(info.path());
    String message = String.format("Class extends @Immutable type %s, but is not immutable: %s", superType, reason);
    return buildDescription(tree).setMessage(message).build();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.Violation) Type(com.sun.tools.javac.code.Type) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol)

Example 2 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.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, "enums should be immutable, and cannot have non-final fields", "enums should only have immutable fields").checkForImmutability(Optional.of(tree), ImmutableSet.of(), getType(tree));
    if (!info.isPresent()) {
        return NO_MATCH;
    }
    String message = "enums should be immutable: " + info.message();
    return buildDescription(tree).setMessage(message).build();
}
Also used : Immutable(com.google.errorprone.annotations.Immutable) Violation(com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.Violation) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) AnnotationTree(com.sun.source.tree.AnnotationTree)

Example 3 with Violation

use of com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.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 (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, "annotations should be immutable, and cannot have non-final fields", "annotations should be immutable").checkForImmutability(Optional.of(tree), ImmutableSet.of(), getType(tree));
    if (!info.isPresent()) {
        return NO_MATCH;
    }
    String message = "annotations should be immutable: " + info.message();
    return buildDescription(tree).setMessage(message).build();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.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.ImmutableAnalysis.Violation in project error-prone by google.

the class ImmutableChecker method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ImmutableAnalysis analysis = new ImmutableAnalysis(this, state, "@Immutable classes cannot have non-final fields", "@Immutable class has mutable field");
    if (tree.getSimpleName().length() == 0) {
        // TODO(cushon): once Java 8 happens, require @Immutable on anonymous classes
        return handleAnonymousClass(tree, state, analysis);
    }
    ImmutableAnnotationInfo annotation = getImmutableAnnotation(tree);
    if (annotation == null) {
        // report an error if it extends/implements any @Immutable-annotated types.
        return checkSubtype(tree, state);
    }
    // of the annotation are "trusted".
    if (WellKnownMutability.KNOWN_IMMUTABLE.containsValue(annotation)) {
        return Description.NO_MATCH;
    }
    // Check that the types in containerOf actually exist
    Set<String> typarams = new HashSet<>();
    for (TypeParameterTree typaram : tree.getTypeParameters()) {
        typarams.add(typaram.getName().toString());
    }
    SetView<String> difference = Sets.difference(annotation.containerOf(), typarams);
    if (!difference.isEmpty()) {
        String message = String.format("could not find type(s) referenced by containerOf: %s", Joiner.on("', '").join(difference));
        return buildDescription(tree).setMessage(message).build();
    }
    // Main path for @Immutable-annotated types:
    //
    // Check that the fields (including inherited fields) are immutable, and
    // validate the type hierarchy superclass.
    Violation info = analysis.checkForImmutability(Optional.of(tree), immutableTypeParametersInScope(ASTHelpers.getSymbol(tree)), ASTHelpers.getType(tree));
    if (!info.isPresent()) {
        return Description.NO_MATCH;
    }
    String message = "type annotated with @Immutable could not be proven immutable: " + info.message();
    return buildDescription(tree).setMessage(message).build();
}
Also used : Violation(com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.Violation) TypeParameterTree(com.sun.source.tree.TypeParameterTree) HashSet(java.util.HashSet)

Aggregations

Violation (com.google.errorprone.bugpatterns.threadsafety.ImmutableAnalysis.Violation)4 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)3 AnnotationTree (com.sun.source.tree.AnnotationTree)2 Immutable (com.google.errorprone.annotations.Immutable)1 TypeParameterTree (com.sun.source.tree.TypeParameterTree)1 Type (com.sun.tools.javac.code.Type)1 HashSet (java.util.HashSet)1