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();
}
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();
}
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();
}
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();
}
Aggregations