use of com.sun.tools.javac.code.Symbol in project error-prone by google.
the class ASTHelpers method getRootAssignable.
/**
* Find the root assignable expression of a chain of field accesses. If there is no root
* (i.e, a bare method call or a static method call), return null.
*
* <p>Examples:
* <pre>
* {@code
* a.trim().intern() ==> a
* a.b.trim().intern() ==> a.b
* this.intValue.foo() ==> this.intValue
* this.foo() ==> this
* intern() ==> null
* String.format() ==> null
* java.lang.String.format() ==> null
* }
* </pre>
*/
public static ExpressionTree getRootAssignable(MethodInvocationTree methodInvocationTree) {
if (!(methodInvocationTree instanceof JCMethodInvocation)) {
throw new IllegalArgumentException("Expected type to be JCMethodInvocation, but was " + methodInvocationTree.getClass());
}
// Check for bare method call, e.g. intern().
if (((JCMethodInvocation) methodInvocationTree).getMethodSelect() instanceof JCIdent) {
return null;
}
// Unwrap the field accesses until you get to an identifier.
ExpressionTree expr = methodInvocationTree;
while (expr instanceof JCMethodInvocation) {
expr = ((JCMethodInvocation) expr).getMethodSelect();
if (expr instanceof JCFieldAccess) {
expr = ((JCFieldAccess) expr).getExpression();
}
}
// We only want assignable identifiers.
Symbol sym = getSymbol(expr);
if (sym instanceof VarSymbol) {
return expr;
}
return null;
}
use of com.sun.tools.javac.code.Symbol 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 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 in project error-prone by google.
the class FindIdentifiers method createFindIdentifiersScanner.
/**
* Finds all identifiers in a tree. Takes an optional stop point as its argument: the depth-first
* walk will stop if this node is encountered.
*/
private static final TreeScanner<Void, Void> createFindIdentifiersScanner(ImmutableSet.Builder<Symbol> builder, @Nullable Tree stoppingPoint) {
return new TreeScanner<Void, Void>() {
@Override
public Void scan(Tree tree, Void unused) {
return Objects.equals(stoppingPoint, tree) ? null : super.scan(tree, unused);
}
@Override
public Void scan(Iterable<? extends Tree> iterable, Void unused) {
if (stoppingPoint != null && iterable != null) {
ImmutableList.Builder<Tree> builder = ImmutableList.builder();
for (Tree t : iterable) {
if (stoppingPoint.equals(t)) {
break;
}
builder.add(t);
}
iterable = builder.build();
}
return super.scan(iterable, unused);
}
@Override
public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
Symbol symbol = ASTHelpers.getSymbol(identifierTree);
if (symbol != null) {
builder.add(symbol);
}
return null;
}
};
}
use of com.sun.tools.javac.code.Symbol in project error-prone by google.
the class FindIdentifiers method findUnusedIdentifiers.
/**
* Finds all variable declarations which are unused at this point in the AST (i.e. they might be
* used further on).
*/
public static ImmutableSet<VarSymbol> findUnusedIdentifiers(VisitorState state) {
ImmutableSet.Builder<VarSymbol> definedVariables = ImmutableSet.builder();
ImmutableSet.Builder<Symbol> usedSymbols = ImmutableSet.builder();
Tree prev = state.getPath().getLeaf();
for (Tree curr : state.getPath().getParentPath()) {
createFindIdentifiersScanner(usedSymbols, prev).scan(curr, null);
switch(curr.getKind()) {
case BLOCK:
// If we see a block then walk over each statement to see if it defines a variable
for (StatementTree statement : ((BlockTree) curr).getStatements()) {
if (statement.equals(prev)) {
// declared/used before us in the tree
break;
}
addIfVariable(statement, definedVariables);
}
break;
case FOR_LOOP:
ForLoopTree forLoop = (ForLoopTree) curr;
forLoop.getInitializer().stream().forEach(t -> addIfVariable(t, definedVariables));
break;
case ENHANCED_FOR_LOOP:
EnhancedForLoopTree enhancedFor = (EnhancedForLoopTree) curr;
addIfVariable(enhancedFor.getVariable(), definedVariables);
break;
default:
break;
}
prev = curr;
}
return ImmutableSet.copyOf(Sets.difference(definedVariables.build(), usedSymbols.build()));
}
Aggregations