use of org.checkerframework.dataflow.qual.TerminatesExecution in project checker-framework by typetools.
the class CFGTranslationPhaseOne method visitMethodInvocation.
@Override
public MethodInvocationNode visitMethodInvocation(MethodInvocationTree tree, Void p) {
// see JLS 15.12.4
// First, compute the receiver, if any (15.12.4.1).
// Second, evaluate the actual arguments, left to right and possibly some arguments are stored
// into an array for variable arguments calls (15.12.4.2).
// Third, test the receiver, if any, for nullness (15.12.4.4).
// Fourth, convert the arguments to the type of the formal parameters (15.12.4.5).
// Fifth, if the method is synchronized, lock the receiving object or class (15.12.4.5).
ExecutableElement method = TreeUtils.elementFromUse(tree);
if (method == null) {
// The method wasn't found, e.g. because of a compilation error.
return null;
}
ExpressionTree methodSelect = tree.getMethodSelect();
assert TreeUtils.isMethodAccess(methodSelect) : "Expected a method access, but got: " + methodSelect;
List<? extends ExpressionTree> actualExprs = tree.getArguments();
// Look up method to invoke and possibly throw NullPointerException
Node receiver = getReceiver(methodSelect);
MethodAccessNode target = new MethodAccessNode(methodSelect, receiver);
ExecutableElement element = TreeUtils.elementFromUse(tree);
if (ElementUtils.isStatic(element) || receiver instanceof ThisNode) {
// No NullPointerException can be thrown, use normal node
extendWithNode(target);
} else {
extendWithNodeWithException(target, nullPointerExceptionType);
}
List<Node> arguments;
if (TreeUtils.isEnumSuper(tree)) {
// Don't convert arguments for enum super calls. The AST contains no actual arguments, while
// the method element expects two arguments, leading to an exception in convertCallArguments.
// Since no actual arguments are present in the AST that is being checked, it shouldn't cause
// any harm to omit the conversions.
// See also BaseTypeVisitor.visitMethodInvocation and QualifierPolymorphism.annotate.
arguments = Collections.emptyList();
} else {
arguments = convertCallArguments(method, actualExprs);
}
// TODO: lock the receiver for synchronized methods
MethodInvocationNode node = new MethodInvocationNode(tree, target, arguments, getCurrentPath());
List<? extends TypeMirror> thrownTypes = element.getThrownTypes();
Set<TypeMirror> thrownSet = new LinkedHashSet<>(thrownTypes.size() + uncheckedExceptionTypes.size());
// Add exceptions explicitly mentioned in the throws clause.
thrownSet.addAll(thrownTypes);
// Add types to account for unchecked exceptions
thrownSet.addAll(uncheckedExceptionTypes);
ExtendedNode extendedNode = extendWithNodeWithExceptions(node, thrownSet);
/* Check for the TerminatesExecution annotation. */
Element methodElement = TreeUtils.elementFromTree(tree);
boolean terminatesExecution = annotationProvider.getDeclAnnotation(methodElement, TerminatesExecution.class) != null;
if (terminatesExecution) {
extendedNode.setTerminatesExecution(true);
}
return node;
}
Aggregations