From 6d806cb616f7ae525d662e61461ca366dda82456 Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Thu, 5 Dec 2024 20:49:35 -0800 Subject: [PATCH] WIP --- .../uber/nullaway/dataflow/AccessPath.java | 19 +++++++++++---- .../com/uber/nullaway/AccessPathsTests.java | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java index a75fd858a9..a7b2d0a4e1 100644 --- a/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java +++ b/nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPath.java @@ -28,6 +28,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.errorprone.VisitorState; +import com.google.errorprone.suppliers.Supplier; +import com.google.errorprone.suppliers.Suppliers; import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.LiteralTree; import com.sun.source.tree.MethodInvocationTree; @@ -75,6 +77,12 @@ */ public final class AccessPath implements MapKey { + private static final Supplier INTEGER_TYPE_SUPPLIER = + Suppliers.typeFromString("java.lang.Integer"); + + private static final Supplier LONG_TYPE_SUPPLIER = + Suppliers.typeFromString("java.lang.Long"); + /** * A prefix added for elements appearing in method invocation APs which represent fields that can * be proven to be class-initialization time constants (i.e. static final fields of a type known @@ -278,14 +286,15 @@ private static Node stripCasts(Node node) { return new NumericMapKey(((LongLiteralNode) argument).getValue()); case METHOD_INVOCATION: MethodAccessNode target = ((MethodInvocationNode) argument).getTarget(); - Node receiver = stripCasts(target.getReceiver()); List 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); + && arguments.size() == 1) { + Type ownerType = ((Symbol.MethodSymbol) target.getMethod()).owner.type; + if (ASTHelpers.isSameType(ownerType, INTEGER_TYPE_SUPPLIER.get(state), state) + || ASTHelpers.isSameType(ownerType, LONG_TYPE_SUPPLIER.get(state), state)) { + return argumentToMapKeySpecifier(arguments.get(0), state, apContext); + } } // Fine to fallthrough: default: diff --git a/nullaway/src/test/java/com/uber/nullaway/AccessPathsTests.java b/nullaway/src/test/java/com/uber/nullaway/AccessPathsTests.java index 1061e9f7c6..c72172d451 100644 --- a/nullaway/src/test/java/com/uber/nullaway/AccessPathsTests.java +++ b/nullaway/src/test/java/com/uber/nullaway/AccessPathsTests.java @@ -434,4 +434,28 @@ public void testAccessUsingExplicitThis() { "}") .doTest(); } + + @Test + public void testValueOfNoReceiver() { + defaultCompilationHelper + .addSourceLines( + "Foo.java", + "package com.uber;", + "import java.util.HashMap;", + "import java.util.Map;", + "public class Foo {", + " private final Map map = new HashMap<>();", + " static Integer valueOf(int i) { return 0; }", + " public void putThenGetFooValueOf() {", + " map.put(valueOf(10), new Object());", + " // BUG: Diagnostic contains: dereferenced expression map.get(valueOf(10)) is @Nullable", + " map.get(valueOf(10)).toString();", + " }", + " public void putThenGetFooIntegerValueOf() {", + " map.put(Integer.valueOf(10), new Object());", + " map.get(Integer.valueOf(10)).toString();", + " }", + "}") + .doTest(); + } }