/
ArrayTests.java
221 lines (208 loc) · 7.57 KB
/
ArrayTests.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package com.uber.nullaway.jspecify;
import com.google.errorprone.CompilationTestHelper;
import com.uber.nullaway.NullAwayTestsBase;
import java.util.Arrays;
import org.junit.Test;
public class ArrayTests extends NullAwayTestsBase {
@Test
public void arrayTopLevelAnnotationDereference() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static Integer @Nullable [] fizz = {1};",
" static void foo() {",
" // BUG: Diagnostic contains: dereferenced expression fizz is @Nullable",
" int bar = fizz.length;",
" }",
" static void bar() {",
" // BUG: Diagnostic contains: dereferenced expression fizz is @Nullable",
" int bar = fizz[0];",
" }",
"}")
.doTest();
}
@Test
public void arrayTopLevelAnnotationAssignment() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" Object foo = new Object();",
" void m( Integer @Nullable [] bar) {",
" // BUG: Diagnostic contains: assigning @Nullable expression to @NonNull field",
" foo = bar;",
" }",
"}")
.doTest();
}
@Test
public void arrayContentsAnnotationDereference() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static @Nullable String [] fizz = {\"1\"};",
" static Object foo = new Object();",
" static void foo() {",
" // BUG: Diagnostic contains: dereferenced expression fizz[0] is @Nullable",
" int bar = fizz[0].length();",
" // OK: valid dereference since only elements of the array can be null",
" foo = fizz.length;",
" }",
"}")
.doTest();
}
@Test
public void arrayContentsAnnotationAssignment() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" Object fizz = new Object();",
" void m( @Nullable Integer [] foo) {",
" // BUG: Diagnostic contains: assigning @Nullable expression to @NonNull field",
" fizz = foo[0];",
" // OK: valid assignment since only elements can be null",
" fizz = foo;",
" }",
"}")
.doTest();
}
/**
* Currently in JSpecify mode, JSpecify syntax only applies to type-use annotations. Declaration
* annotations preserve their existing behavior, with annotations being treated on the top-level
* type. We will very likely revisit this design in the future.
*/
@Test
public void arrayDeclarationAnnotation() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import javax.annotation.Nullable;",
"class Test {",
" static @Nullable String [] fizz = {\"1\"};",
" static Object o1 = new Object();",
" static void foo() {",
" // This should not report an error while using JSpecify type-use annotation",
" // BUG: Diagnostic contains: assigning @Nullable expression to @NonNull field",
" o1 = fizz;",
" // This should not report an error while using JSpecify type-use annotation",
" // BUG: Diagnostic contains: dereferenced expression fizz is @Nullable",
" o1 = fizz.length;",
" }",
"}")
.doTest();
}
@Test
public void arrayContentsAndTopLevelAnnotation() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static @Nullable String @Nullable [] fizz = {\"1\"};",
" static Object foo = new Object();",
" static void foo() {",
" if (fizz != null) {",
" String s = fizz[0];",
" // BUG: Diagnostic contains: dereferenced expression s is @Nullable",
" int l1 = s.length();",
" if (s != null){",
" // OK: handled by null check",
" int l2 = s.length();",
" }",
" }",
" }",
"}")
.doTest();
}
@Test
public void nullableAssignmentNonnullArray() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static String [] foo = new String[10];",
" static void foo() {",
" // BUG: Diagnostic contains: Writing @Nullable expression into array with @NonNull contents",
" foo[1] = null;",
" }",
"}")
.doTest();
}
@Test
public void nullableAssignmentNullableArray() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static @Nullable String [] foo = new String[10];",
" static void foo() {",
" // OK: since array elements are @Nullable",
" foo[1] = null;",
" }",
"}")
.doTest();
}
@Test
public void nullableAssignmentLocalArray() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static void foo() {",
" String [] nonNullArray = new String[10];",
" @Nullable String [] nullableArray = new String[10];",
" // BUG: Diagnostic contains: Writing @Nullable expression into array with @NonNull contents",
" nonNullArray[1] = null;",
" // OK: since array elements are @Nullable",
" nullableArray[1] = null;",
" }",
"}")
.doTest();
}
@Test
public void nullableAssignmentParameterArray() {
makeHelper()
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.Nullable;",
"class Test {",
" static void fizz(String[] nonNullArray, @Nullable String[] nullableArray) {",
" // BUG: Diagnostic contains: Writing @Nullable expression into array with @NonNull contents",
" nonNullArray[1] = null;",
" // OK: since array elements are @Nullable",
" nullableArray[1] = null;",
" }",
" public static void main(String[] args) {",
" String[] foo = new String[10];",
" @Nullable String[] bar = new String[10];",
" fizz(foo, bar);",
" }",
"}")
.doTest();
}
private CompilationTestHelper makeHelper() {
return makeTestHelperWithArgs(
Arrays.asList(
"-XepOpt:NullAway:AnnotatedPackages=com.uber", "-XepOpt:NullAway:JSpecifyMode=true"));
}
}