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