use of com.sun.tools.javac.code.Symbol.ClassSymbol in project error-prone by google.
the class FunctionalInterfaceClash method matchClass.
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
ClassSymbol origin = getSymbol(tree);
Types types = state.getTypes();
// collect declared and inherited methods whose signature contains a functional interface
Multimap<String, MethodSymbol> methods = HashMultimap.create();
for (Symbol sym : types.membersClosure(getType(tree), /*skipInterface=*/
false).getSymbols()) {
if (!(sym instanceof MethodSymbol)) {
continue;
}
if (isBugCheckerSuppressed((MethodSymbol) sym)) {
continue;
}
MethodSymbol msym = (MethodSymbol) sym;
if (msym.getParameters().stream().noneMatch(p -> maybeFunctionalInterface(p.type, types))) {
continue;
}
if (msym.isConstructor() && !msym.owner.equals(origin)) {
continue;
}
methods.put(functionalInterfaceSignature(state, msym), msym);
}
// (don't report clashes between inherited members)
for (Tree member : tree.getMembers()) {
if (!(member instanceof MethodTree)) {
continue;
}
MethodSymbol msym = getSymbol((MethodTree) member);
if (msym.getParameters().stream().noneMatch(p -> maybeFunctionalInterface(p.type, types))) {
continue;
}
Collection<MethodSymbol> clash = new ArrayList<>(methods.removeAll(functionalInterfaceSignature(state, msym)));
clash.remove(msym);
// ignore inherited methods that are overridden in the original class
clash.removeIf(m -> msym.overrides(m, origin, types, false));
if (!clash.isEmpty()) {
String message = "When passing lambda arguments to this function, callers will need a cast to" + " disambiguate with: " + clash.stream().map(m -> Signatures.prettyMethodSignature(origin, m)).collect(joining("\n "));
state.reportMatch(buildDescription(member).setMessage(message).build());
}
}
return NO_MATCH;
}
use of com.sun.tools.javac.code.Symbol.ClassSymbol in project error-prone by google.
the class LiteralClassName method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!CLASS_NAME.matches(tree, state)) {
return NO_MATCH;
}
String className = constValue(getOnlyElement(tree.getArguments()), String.class);
if (className == null) {
return NO_MATCH;
}
if (className.startsWith("[")) {
// TODO(cushon): consider handling arrays
return NO_MATCH;
}
Type type = state.getTypeFromString(className);
if (type == null) {
return NO_MATCH;
}
ClassSymbol owner = getSymbol(state.findEnclosing(ClassTree.class));
Enter enter = Enter.instance(state.context);
if (!Resolve.instance(state.context).isAccessible(enter.getEnv(owner), type.tsym)) {
return NO_MATCH;
}
SuggestedFix.Builder fix = SuggestedFix.builder();
String replaceWith = String.format("%s.class", qualifyType(state, fix, state.getTypes().erasure(type)));
if (state.getPath().getParentPath().getLeaf().getKind() == Tree.Kind.EXPRESSION_STATEMENT) {
fix.addStaticImport("java.util.Objects.requireNonNull");
replaceWith = String.format("requireNonNull(%s)", replaceWith);
}
fix.replace(tree, replaceWith);
return describeMatch(tree, fix.build());
}
use of com.sun.tools.javac.code.Symbol.ClassSymbol in project error-prone by google.
the class HeldLockAnalyzer method handleMonitorGuards.
private static HeldLockSet handleMonitorGuards(VisitorState state, HeldLockSet locks) {
JCNewClass newClassTree = ASTHelpers.findEnclosingNode(state.getPath(), JCNewClass.class);
if (newClassTree == null) {
return locks;
}
Symbol clazzSym = ASTHelpers.getSymbol(newClassTree.clazz);
if (!(clazzSym instanceof ClassSymbol)) {
return locks;
}
if (!((ClassSymbol) clazzSym).fullname.contentEquals(MONITOR_GUARD_CLASS)) {
return locks;
}
Optional<GuardedByExpression> lockExpression = GuardedByBinder.bindExpression(Iterables.getOnlyElement(newClassTree.getArguments()), state);
if (!lockExpression.isPresent()) {
return locks;
}
return locks.plus(lockExpression.get());
}
use of com.sun.tools.javac.code.Symbol.ClassSymbol 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.sun.tools.javac.code.Symbol.ClassSymbol in project error-prone by google.
the class ImmutableChecker method checkSubtype.
// Strong behavioural subtyping
/** Check for classes without {@code @Immutable} that have immutable supertypes. */
private Description checkSubtype(ClassTree tree, VisitorState state) {
ClassSymbol sym = ASTHelpers.getSymbol(tree);
if (sym == null) {
return Description.NO_MATCH;
}
Type superType = immutableSupertype(sym, state);
if (superType == null) {
return Description.NO_MATCH;
}
String message = String.format("Class extends @Immutable type %s, but is not annotated as immutable", superType);
Fix fix = SuggestedFix.builder().prefixWith(tree, "@Immutable ").addImport(Immutable.class.getName()).build();
return buildDescription(tree).setMessage(message).addFix(fix).build();
}
Aggregations