in nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java [273:303]
private static MapKey argumentToMapKeySpecifier(
Node argument, VisitorState state, AccessPathContext apContext) {
// Required to have Node type match Tree type in some instances.
if (argument instanceof WideningConversionNode) {
argument = ((WideningConversionNode) argument).getOperand();
}
// A switch at the Tree level should be faster than multiple if checks at the Node level.
switch (castToNonNull(argument.getTree()).getKind()) {
case STRING_LITERAL:
return new StringMapKey(((StringLiteralNode) argument).getValue());
case INT_LITERAL:
return new NumericMapKey(((IntegerLiteralNode) argument).getValue());
case LONG_LITERAL:
return new NumericMapKey(((LongLiteralNode) argument).getValue());
case METHOD_INVOCATION:
MethodAccessNode target = ((MethodInvocationNode) argument).getTarget();
Node receiver = stripCasts(target.getReceiver());
List<Node> arguments = ((MethodInvocationNode) argument).getArguments();
// Check for int/long boxing.
if (target.getMethod().getSimpleName().toString().equals("valueOf")
&& arguments.size() == 1
&& castToNonNull(receiver.getTree()).getKind().equals(Tree.Kind.IDENTIFIER)
&& (receiver.toString().equals("Integer") || receiver.toString().equals("Long"))) {
return argumentToMapKeySpecifier(arguments.get(0), state, apContext);
}
// Fine to fallthrough:
default:
// Every other type of expression, including variables, field accesses, new A(...), etc.
return getAccessPathForNode(argument, state, apContext); // Every AP is a MapKey too
}
}