use of com.sun.source.tree.MethodInvocationTree in project bazel by bazelbuild.
the class TreeUtils method containsThisConstructorInvocation.
/**
* @return true if the first statement in the body is a self constructor
* invocation within a constructor
*/
public static final boolean containsThisConstructorInvocation(MethodTree node) {
if (!TreeUtils.isConstructor(node) || node.getBody().getStatements().isEmpty())
return false;
StatementTree st = node.getBody().getStatements().get(0);
if (!(st instanceof ExpressionStatementTree) || !(((ExpressionStatementTree) st).getExpression() instanceof MethodInvocationTree))
return false;
MethodInvocationTree invocation = (MethodInvocationTree) ((ExpressionStatementTree) st).getExpression();
return "this".contentEquals(TreeUtils.methodName(invocation));
}
use of com.sun.source.tree.MethodInvocationTree in project bazel by bazelbuild.
the class TreeUtils method isMethodInvocation.
/**
* Returns true if the given element is an invocation of the method, or
* of any method that overrides that one.
*/
public static boolean isMethodInvocation(Tree tree, ExecutableElement method, ProcessingEnvironment env) {
if (!(tree instanceof MethodInvocationTree))
return false;
MethodInvocationTree methInvok = (MethodInvocationTree) tree;
ExecutableElement invoked = TreeUtils.elementFromUse(methInvok);
return isMethod(invoked, method, env);
}
use of com.sun.source.tree.MethodInvocationTree in project error-prone by google.
the class ChainingConstructorIgnoresParameter method evaluateCallers.
private Description evaluateCallers(MethodSymbol symbol) {
List<VariableTree> paramTypes = paramTypesForMethod.get(symbol);
if (paramTypes == null) {
// We haven't seen the declaration yet. We'll evaluate the call when we do.
return NO_MATCH;
}
for (Caller caller : callersToEvaluate.removeAll(symbol)) {
VisitorState state = caller.state;
MethodInvocationTree invocation = caller.tree;
MethodTree callerConstructor = state.findEnclosing(MethodTree.class);
if (callerConstructor == null) {
// impossible, at least in compilable code?
continue;
}
Map<String, Type> availableParams = indexTypeByName(callerConstructor.getParameters());
/*
* TODO(cpovirk): Better handling of varargs: If the last parameter type is varargs and it is
* called as varargs (rather than by passing an array), then rewrite the parameter types to
* (p0, p1, ..., p[n-2], p[n-1] = element type of varargs parameter if an argument is
* supplied, p[n] = ditto, etc.). For now, we settle for not crashing in the face of a
* mismatch between the number of parameters declared and the number supplied.
*
* (Use MethodSymbol.isVarArgs.)
*/
for (int i = 0; i < paramTypes.size() && i < invocation.getArguments().size(); i++) {
VariableTree formalParam = paramTypes.get(i);
String formalParamName = formalParam.getName().toString();
Type formalParamType = getType(formalParam.getType());
Type availableParamType = availableParams.get(formalParamName);
ExpressionTree actualParam = invocation.getArguments().get(i);
if (/*
* The caller has no param of this type. (Or if it did, we couldn't determine the type.
* Does that ever happen?) If the param doesn't exist, the caller can't be failing to
* pass it.
*/
availableParamType == null || /*
* We couldn't determine the type of the formal parameter. (Does this ever happen?)
*/
formalParamType == null || /*
* The caller is passing the expected parameter (or "ImmutableList.copyOf(parameter),"
* "new File(parameter)," etc.).
*/
referencesIdentifierWithName(formalParamName, actualParam, state)) {
continue;
}
if (state.getTypes().isAssignable(availableParamType, formalParamType)) {
reportMatch(invocation, state, actualParam, formalParamName);
}
/*
* If formal parameter is of an incompatible type, the caller might in theory still intend
* to pass a dervied expression. For example, "Foo(String file)" might intend to call
* "Foo(File file)" by passing "new File(file)." If this comes up in practice, we could
* provide the dummy suggested fix "someExpression(formalParamName)." However, my research
* suggests that this will rarely if ever be what the user wants.
*/
}
}
// All matches are reported through reportMatch calls instead of return values.
return NO_MATCH;
}
use of com.sun.source.tree.MethodInvocationTree in project error-prone by google.
the class FunctionalInterfaceMethodChanged method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
ClassTree enclosingClazz = ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class);
if (tree.getModifiers().getFlags().contains(Modifier.DEFAULT) && IS_FUNCTIONAL_INTERFACE.matches(enclosingClazz, state)) {
Types types = Types.instance(state.context);
Set<Symbol> functionalSuperInterfaceSams = enclosingClazz.getImplementsClause().stream().filter(t -> IS_FUNCTIONAL_INTERFACE.matches(t, state)).map(ASTHelpers::getSymbol).map(TypeSymbol.class::cast).map(// TypeSymbol to single abstract method of the type
types::findDescriptorSymbol).collect(toImmutableSet());
// We designate an override of a superinterface SAM "behavior preserving" if it just
// calls the SAM of this interface.
Symbol thisInterfaceSam = types.findDescriptorSymbol(ASTHelpers.getSymbol(enclosingClazz));
// relatively crude: doesn't verify that the same args are passed in the same order
// so it can get false positives for behavior-preservingness (false negatives for the check)
TreeVisitor<Boolean, VisitorState> behaviorPreserving = new SimpleTreeVisitor<Boolean, VisitorState>(false) {
@Override
public Boolean visitMethod(MethodTree node, VisitorState state) {
return node.getBody() != null && node.getBody().accept(this, state);
}
@Override
public Boolean visitBlock(BlockTree node, VisitorState state) {
return node.getStatements().size() == 1 && Iterables.getOnlyElement(node.getStatements()).accept(this, state);
}
@Override
public Boolean visitExpressionStatement(ExpressionStatementTree node, VisitorState state) {
return node.getExpression().accept(this, state);
}
@Override
public Boolean visitReturn(ReturnTree node, VisitorState state) {
return node.getExpression().accept(this, state);
}
@Override
public Boolean visitMethodInvocation(MethodInvocationTree node, VisitorState state) {
return ASTHelpers.getSymbol(node) == thisInterfaceSam;
}
};
if (!Collections.disjoint(ASTHelpers.findSuperMethods(ASTHelpers.getSymbol(tree), types), functionalSuperInterfaceSams) && !tree.accept(behaviorPreserving, state)) {
return describeMatch(tree);
}
}
return Description.NO_MATCH;
}
use of com.sun.source.tree.MethodInvocationTree in project error-prone by google.
the class InfiniteRecursion method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (tree.getBody() == null || tree.getBody().getStatements().size() != 1) {
return NO_MATCH;
}
Tree statement = TreeInfo.skipParens((JCTree) Iterables.getOnlyElement(tree.getBody().getStatements()));
ExpressionTree expr = statement.accept(new SimpleTreeVisitor<ExpressionTree, Void>() {
@Override
public ExpressionTree visitExpressionStatement(ExpressionStatementTree tree, Void unused) {
return tree.getExpression();
}
@Override
public ExpressionTree visitReturn(ReturnTree tree, Void unused) {
return tree.getExpression();
}
}, null);
if (!(expr instanceof MethodInvocationTree)) {
return NO_MATCH;
}
ExpressionTree select = ((MethodInvocationTree) expr).getMethodSelect();
switch(select.getKind()) {
case IDENTIFIER:
break;
case MEMBER_SELECT:
ExpressionTree receiver = ((MemberSelectTree) select).getExpression();
if (receiver.getKind() != Kind.IDENTIFIER) {
return NO_MATCH;
}
if (!((IdentifierTree) receiver).getName().contentEquals("this")) {
return NO_MATCH;
}
break;
default:
return NO_MATCH;
}
MethodSymbol sym = ASTHelpers.getSymbol(tree);
if (sym == null || !sym.equals(ASTHelpers.getSymbol(expr))) {
return NO_MATCH;
}
return describeMatch(statement);
}
Aggregations