use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class ASTHelpers method findMatchingMethods.
/**
* Finds all methods in any superclass of {@code startClass} with a certain {@code name} that
* match the given {@code predicate}.
*
* @return The (possibly empty) set of methods in any superclass that match {@code predicate} and
* have the given {@code name}.
*/
public static Set<MethodSymbol> findMatchingMethods(Name name, final Predicate<MethodSymbol> predicate, Type startClass, Types types) {
Filter<Symbol> matchesMethodPredicate = sym -> sym instanceof MethodSymbol && predicate.apply((MethodSymbol) sym);
Set<MethodSymbol> matchingMethods = new HashSet<>();
// Iterate over all classes and interfaces that startClass inherits from.
for (Type superClass : types.closure(startClass)) {
// Iterate over all the methods declared in superClass.
TypeSymbol superClassSymbol = superClass.tsym;
Scope superClassSymbols = superClassSymbol.members();
if (superClassSymbols != null) {
// Can be null if superClass is a type variable
for (Symbol symbol : superClassSymbols.getSymbolsByName(name, matchesMethodPredicate, NON_RECURSIVE)) {
// By definition of the filter, we know that the symbol is a MethodSymbol.
matchingMethods.add((MethodSymbol) symbol);
}
}
}
return matchingMethods;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class AmbiguousMethodReference method matchClass.
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
ClassSymbol origin = getSymbol(tree);
Types types = state.getTypes();
Iterable<Symbol> members = types.membersClosure(getType(tree), /*skipInterface=*/
false).getSymbols();
// collect declared and inherited methods, grouped by reference descriptor
Map<String, List<MethodSymbol>> methods = stream(members.spliterator(), false).filter(MethodSymbol.class::isInstance).map(MethodSymbol.class::cast).filter(m -> m.isConstructor() || m.owner.equals(origin)).collect(groupingBy(m -> methodReferenceDescriptor(types, m), toCollection(ArrayList::new)));
// look for groups of ambiguous method references
for (Tree member : tree.getMembers()) {
if (!(member instanceof MethodTree)) {
continue;
}
MethodSymbol msym = getSymbol((MethodTree) member);
if (isSuppressed(msym)) {
continue;
}
List<MethodSymbol> clash = methods.remove(methodReferenceDescriptor(types, msym));
if (clash == null) {
continue;
}
clash.remove(msym);
// ignore overridden inherited methods and hidden interface methods
clash.removeIf(m -> types.isSubSignature(msym.type, m.type));
if (clash.isEmpty()) {
continue;
}
String message = String.format("This method's reference is ambiguous, its name and functional interface type" + " are the same as: %s", clash.stream().map(m -> Signatures.prettyMethodSignature(origin, m)).collect(joining(", ")));
state.reportMatch(buildDescription(member).setMessage(message).build());
}
return NO_MATCH;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class BadAnnotationImplementation method matchClass.
@Override
public Description matchClass(ClassTree classTree, final VisitorState state) {
if (!CLASS_TREE_MATCHER.matches(classTree, state)) {
return Description.NO_MATCH;
}
// If this is an enum that is trying to implement Annotation, give a special error message.
if (classTree.getKind() == Kind.ENUM) {
return buildDescription(classTree).setMessage("Enums cannot correctly implement Annotation because their equals and hashCode " + "methods are final. Consider using AutoAnnotation instead of implementing " + "Annotation by hand.").build();
}
// Otherwise walk up type hierarchy looking for equals and hashcode methods
MethodSymbol equals = null;
MethodSymbol hashCode = null;
final Types types = state.getTypes();
Name equalsName = state.getName("equals");
Predicate<MethodSymbol> equalsPredicate = new Predicate<MethodSymbol>() {
@Override
public boolean apply(MethodSymbol methodSymbol) {
return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().size() == 1 && types.isSameType(methodSymbol.getParameters().get(0).type, state.getSymtab().objectType);
}
};
Name hashCodeName = state.getName("hashCode");
Predicate<MethodSymbol> hashCodePredicate = new Predicate<MethodSymbol>() {
@Override
public boolean apply(MethodSymbol methodSymbol) {
return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().isEmpty();
}
};
for (Type sup : types.closure(ASTHelpers.getSymbol(classTree).type)) {
if (equals == null) {
equals = getMatchingMethod(sup, equalsName, equalsPredicate);
}
if (hashCode == null) {
hashCode = getMatchingMethod(sup, hashCodeName, hashCodePredicate);
}
}
Verify.verifyNotNull(equals);
Verify.verifyNotNull(hashCode);
Symbol objectSymbol = state.getSymtab().objectType.tsym;
if (equals.owner.equals(objectSymbol) || hashCode.owner.equals(objectSymbol)) {
return describeMatch(classTree);
}
return Description.NO_MATCH;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class FindIdentifiers method inStaticContext.
/** Returns true iff the leaf node of the {@code path} occurs in a JLS 8.3.1 static context. */
private static boolean inStaticContext(TreePath path) {
Tree prev = path.getLeaf();
path = path.getParentPath();
ClassSymbol enclosingClass = ASTHelpers.getSymbol(ASTHelpers.findEnclosingNode(path, ClassTree.class));
ClassSymbol directSuperClass = (ClassSymbol) enclosingClass.getSuperclass().tsym;
for (Tree tree : path) {
switch(tree.getKind()) {
case METHOD:
return ASTHelpers.getSymbol(tree).isStatic();
case // static initializer
BLOCK:
if (((BlockTree) tree).isStatic()) {
return true;
}
break;
case // variable initializer of static variable
VARIABLE:
VariableTree variableTree = (VariableTree) tree;
VarSymbol variableSym = ASTHelpers.getSymbol(variableTree);
if (variableSym.getKind() == ElementKind.FIELD) {
return Objects.equals(variableTree.getInitializer(), prev) && variableSym.isStatic();
}
break;
case // JLS 8.8.7.1 explicit constructor invocation
METHOD_INVOCATION:
MethodSymbol methodSym = ASTHelpers.getSymbol((MethodInvocationTree) tree);
if (methodSym == null) {
// visibility)
return true;
}
if (methodSym.isConstructor() && (Objects.equals(methodSym.owner, enclosingClass) || Objects.equals(methodSym.owner, directSuperClass))) {
return true;
}
break;
default:
break;
}
prev = tree;
}
return false;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class ChainingConstructorIgnoresParameter method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
MethodSymbol symbol = getSymbol(tree);
// TODO(cpovirk): determine whether anyone might be calling Foo.this()
if (!isIdentifierWithName(tree.getMethodSelect(), "this")) {
return NO_MATCH;
}
callersToEvaluate.put(symbol, new Caller(tree, state));
return evaluateCallers(symbol);
}
Aggregations