[java-inspections] Mark standard collection constructors as pure

IDEA-299423 NPE false positive in static analysis involving collection emptiness check

GitOrigin-RevId: c15b5117e0c58ebbe5617d221db66ecf969f5204
This commit is contained in:
Tagir Valeev
2022-08-08 14:16:01 +00:00
committed by intellij-monorepo-bot
parent 2271d25144
commit f8bd662378
3 changed files with 131 additions and 0 deletions
@@ -0,0 +1,20 @@
// IDEA-299423
import java.util.*;
class Test {
private static void exampleThree() {
final Queue<String> queue1 = new ArrayDeque<>(List.of("foo1", "bar1"));
final Queue<String> queue2 = new ArrayDeque<>(List.of("foo2", "bar2"));
final Queue<String> queue3 = new ArrayDeque<>(List.of("foo3", "bar3"));
if(!queue1.isEmpty() && !queue2.isEmpty() && !queue3.isEmpty()) {
final String poll1 = queue1.poll();
final String poll2 = queue2.poll();
final String poll3 = queue3.poll();
// NPE warning for poll2.getBytes() and poll3.getBytes() because poll2 and poll3 might be null
if (poll1.getBytes().length == poll2.getBytes().length || poll3.getBytes().length != 0) {
// ...
}
}
}
}
@@ -21,4 +21,5 @@ public class DataFlowInspection9Test extends DataFlowInspectionTestCase {
public void testMutabilityJdk9() { doTest();}
public void testMutabilityInferred() { doTest(); }
public void testObjectsRequireNonNullElse() { doTest(); }
public void testNewCollectionAliasing() { doTest(); }
}
@@ -30,6 +30,21 @@
<item name='java.util.AbstractMap java.util.Set&lt;java.util.Map.Entry&lt;K,V&gt;&gt; entrySet()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='java.util.ArrayDeque ArrayDeque()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.ArrayDeque ArrayDeque(int)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.ArrayDeque ArrayDeque(java.util.Collection&lt;? extends E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.ArrayDeque E element()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
@@ -72,12 +87,27 @@
<item name='java.util.ArrayDeque void push(E) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='java.util.ArrayList ArrayList()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.ArrayList ArrayList(int)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.ArrayList ArrayList(int) 0'>
<annotation name='org.jetbrains.annotations.Range'>
<val name="from" val="0"/>
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
</annotation>
</item>
<item name='java.util.ArrayList ArrayList(java.util.Collection&lt;? extends E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name="java.util.ArrayList ArrayList(java.util.Collection&lt;? extends E&gt;) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
<annotation name='org.intellij.lang.annotations.Flow'>
@@ -2945,30 +2975,70 @@
<val name="to" val="61"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap(int)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap(int) 0'>
<annotation name='org.jetbrains.annotations.Range'>
<val name="from" val="0"/>
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap(int, float)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap(int, float) 0'>
<annotation name='org.jetbrains.annotations.Range'>
<val name="from" val="0"/>
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
</annotation>
</item>
<item name='java.util.HashMap HashMap(java.util.Map&lt;? extends K,? extends V&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(int)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(int) 0'>
<annotation name='org.jetbrains.annotations.Range'>
<val name="from" val="0"/>
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(int, float)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(int, float) 0'>
<annotation name='org.jetbrains.annotations.Range'>
<val name="from" val="0"/>
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(java.util.Collection&lt;? extends E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.HashSet HashSet(java.util.Collection&lt;? extends E&gt;) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='org.intellij.lang.annotations.Flow'>
@@ -3878,6 +3948,36 @@
<item name="java.util.TimeZone java.util.TimeZone getTimeZone(java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NonNls" />
</item>
<item name='java.util.TreeMap TreeMap()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeMap TreeMap(java.util.Comparator&lt;? super K&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeMap TreeMap(java.util.Map&lt;? extends K,? extends V&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeMap TreeMap(java.util.SortedMap&lt;K,? extends V&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeSet TreeSet()'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeSet TreeSet(java.util.Collection&lt;? extends E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeSet TreeSet(java.util.Collection&lt;? extends E&gt;) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='org.intellij.lang.annotations.Flow'>
@@ -3885,6 +3985,16 @@
<val name="targetIsContainer" val="true"/>
</annotation>
</item>
<item name='java.util.TreeSet TreeSet(java.util.Comparator&lt;? super E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name='java.util.TreeSet TreeSet(java.util.SortedSet&lt;E&gt;)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val name="pure" val="true"/>
</annotation>
</item>
<item name="java.util.UUID">
<annotation name="org.jetbrains.annotations.NonNls" />
</item>