use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class InitializationTransfer method initializedFieldsAfterCall.
/**
* Returns the fields that can safely be considered initialized after the method call {@code
* node}.
*
* @param node a method call
* @return the fields that are initialized after the method call
*/
protected List<VariableElement> initializedFieldsAfterCall(MethodInvocationNode node) {
List<VariableElement> result = new ArrayList<>();
MethodInvocationTree tree = node.getTree();
ExecutableElement method = TreeUtils.elementFromUse(tree);
boolean isConstructor = method.getSimpleName().contentEquals("<init>");
Node receiver = node.getTarget().getReceiver();
String methodString = tree.getMethodSelect().toString();
// invariant fields are guaranteed to be initialized.
if (isConstructor && receiver instanceof ThisNode && methodString.equals("this")) {
ClassTree clazz = TreePathUtil.enclosingClass(analysis.getTypeFactory().getPath(tree));
TypeElement clazzElem = TreeUtils.elementFromDeclaration(clazz);
markInvariantFieldsAsInitialized(result, clazzElem);
}
// invariant fields of any super class are guaranteed to be initialized.
if (isConstructor && receiver instanceof ThisNode && methodString.equals("super")) {
ClassTree clazz = TreePathUtil.enclosingClass(analysis.getTypeFactory().getPath(tree));
TypeElement clazzElem = TreeUtils.elementFromDeclaration(clazz);
TypeMirror superClass = clazzElem.getSuperclass();
while (superClass != null && superClass.getKind() != TypeKind.NONE) {
clazzElem = (TypeElement) analysis.getTypes().asElement(superClass);
superClass = clazzElem.getSuperclass();
markInvariantFieldsAsInitialized(result, clazzElem);
}
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class I18nFormatterTreeUtil method makeFormatCallCategories.
public Result<I18nConversionCategory[]> makeFormatCallCategories(MethodInvocationNode node, I18nFormatterAnnotatedTypeFactory atypeFactory) {
Map<String, String> translations = atypeFactory.translations;
Node firstParam = node.getArgument(0);
Result<I18nConversionCategory[]> ret = new Result<>(null, node.getTree());
// Now only work with a literal string
if (firstParam instanceof StringLiteralNode) {
String s = ((StringLiteralNode) firstParam).getValue();
if (translations.containsKey(s)) {
String value = translations.get(s);
ret = new Result<>(I18nFormatUtil.formatParameterCategories(value), node.getTree());
}
}
return ret;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class JavaExpression method fromNode.
/**
* We ignore operations such as widening and narrowing when computing the internal representation.
*
* @param receiverNode a node to convert to a JavaExpression
* @return the internal representation of the given node. Might contain {@link Unknown}.
*/
public static JavaExpression fromNode(Node receiverNode) {
JavaExpression result = null;
if (receiverNode instanceof FieldAccessNode) {
result = fromNodeFieldAccess((FieldAccessNode) receiverNode);
} else if (receiverNode instanceof ExplicitThisNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof ThisNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof SuperNode) {
result = new ThisReference(receiverNode.getType());
} else if (receiverNode instanceof LocalVariableNode) {
LocalVariableNode lv = (LocalVariableNode) receiverNode;
result = new LocalVariable(lv);
} else if (receiverNode instanceof ArrayAccessNode) {
ArrayAccessNode a = (ArrayAccessNode) receiverNode;
result = fromArrayAccess(a);
} else if (receiverNode instanceof StringConversionNode) {
// ignore string conversion
return fromNode(((StringConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof WideningConversionNode) {
// ignore widening
return fromNode(((WideningConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof NarrowingConversionNode) {
// ignore narrowing
return fromNode(((NarrowingConversionNode) receiverNode).getOperand());
} else if (receiverNode instanceof UnaryOperationNode) {
UnaryOperationNode uopn = (UnaryOperationNode) receiverNode;
return new UnaryOperation(uopn, fromNode(uopn.getOperand()));
} else if (receiverNode instanceof BinaryOperationNode) {
BinaryOperationNode bopn = (BinaryOperationNode) receiverNode;
return new BinaryOperation(bopn, fromNode(bopn.getLeftOperand()), fromNode(bopn.getRightOperand()));
} else if (receiverNode instanceof ClassNameNode) {
ClassNameNode cn = (ClassNameNode) receiverNode;
result = new ClassName(cn.getType());
} else if (receiverNode instanceof ValueLiteralNode) {
ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
result = new ValueLiteral(vn.getType(), vn);
} else if (receiverNode instanceof ArrayCreationNode) {
ArrayCreationNode an = (ArrayCreationNode) receiverNode;
List<@Nullable JavaExpression> dimensions = CollectionsPlume.mapList(JavaExpression::fromNode, an.getDimensions());
List<JavaExpression> initializers = CollectionsPlume.mapList(JavaExpression::fromNode, an.getInitializers());
result = new ArrayCreation(an.getType(), dimensions, initializers);
} else if (receiverNode instanceof MethodInvocationNode) {
MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
MethodInvocationTree t = mn.getTree();
if (t == null) {
throw new BugInCF("Unexpected null tree for node: " + mn);
}
assert TreeUtils.isUseOfElement(t) : "@AssumeAssertion(nullness): tree kind";
ExecutableElement invokedMethod = TreeUtils.elementFromUse(t);
// Note that the method might be nondeterministic.
List<JavaExpression> parameters = CollectionsPlume.mapList(JavaExpression::fromNode, mn.getArguments());
JavaExpression methodReceiver;
if (ElementUtils.isStatic(invokedMethod)) {
methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
} else {
methodReceiver = fromNode(mn.getTarget().getReceiver());
}
result = new MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
}
if (result == null) {
result = new Unknown(receiverNode);
}
return result;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode 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;
}
use of org.checkerframework.dataflow.cfg.node.MethodInvocationNode in project checker-framework by typetools.
the class CFGTranslationPhaseOne method unbox.
/**
* If the input node is a boxed type, unbox it, otherwise leave it alone.
*
* @param node in input node
* @return a Node representing the unboxed version of the input, which may simply be the input
* node
*/
protected Node unbox(Node node) {
if (TypesUtils.isBoxedPrimitive(node.getType())) {
MemberSelectTree primValueSelect = treeBuilder.buildPrimValueMethodAccess(node.getTree());
handleArtificialTree(primValueSelect);
MethodAccessNode primValueAccess = new MethodAccessNode(primValueSelect, node);
primValueAccess.setInSource(false);
// Method access may throw NullPointerException
insertNodeWithExceptionsAfter(primValueAccess, Collections.singleton(nullPointerExceptionType), node);
MethodInvocationTree primValueCall = treeBuilder.buildMethodInvocation(primValueSelect);
handleArtificialTree(primValueCall);
Node unboxed = new MethodInvocationNode(primValueCall, primValueAccess, Collections.emptyList(), getCurrentPath());
unboxed.setInSource(false);
// Add Throwable to account for unchecked exceptions
addToConvertedLookupMap(node.getTree(), unboxed);
insertNodeWithExceptionsAfter(unboxed, uncheckedExceptionTypes, primValueAccess);
return unboxed;
} else {
return node;
}
}
Aggregations