Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2010, 2011 GK Software AG and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* Stephan Herrmann - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.jdt.core.tests.compiler.regression; |
12 |
|
13 |
import java.util.Map; |
14 |
|
15 |
import junit.framework.Test; |
16 |
|
17 |
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
18 |
|
19 |
public class NullAnnotationTest extends AbstractComparableTest { |
20 |
|
21 |
public NullAnnotationTest(String name) { |
22 |
super(name); |
23 |
} |
24 |
|
25 |
// Static initializer to specify tests subset using TESTS_* static variables |
26 |
// All specified tests which do not belong to the class are skipped... |
27 |
static { |
28 |
// TESTS_NAMES = new String[] { "test_parameter_contract_inheritance" }; |
29 |
// TESTS_NUMBERS = new int[] { 561 }; |
30 |
// TESTS_RANGE = new int[] { 1, 2049 }; |
31 |
} |
32 |
|
33 |
public static Test suite() { |
34 |
return buildComparableTestSuite(testClass()); |
35 |
} |
36 |
|
37 |
public static Class testClass() { |
38 |
return NullAnnotationTest.class; |
39 |
} |
40 |
|
41 |
// Conditionally augment problem detection settings |
42 |
static boolean setNullRelatedOptions = true; |
43 |
protected Map getCompilerOptions() { |
44 |
Map defaultOptions = super.getCompilerOptions(); |
45 |
if (setNullRelatedOptions) { |
46 |
defaultOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
47 |
defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullReference, CompilerOptions.ERROR); |
48 |
defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR); |
49 |
defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE); |
50 |
defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED); |
51 |
|
52 |
// leave new options at these defaults: |
53 |
// defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, CompilerOptions.ERROR); |
54 |
// defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); |
55 |
// defaultOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.WARNING); |
56 |
|
57 |
defaultOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.eclipse.jdt.annotation.Nullable"); |
58 |
defaultOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.eclipse.jdt.annotation.NonNull"); |
59 |
defaultOptions.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.ENABLED); |
60 |
defaultOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
61 |
} |
62 |
return defaultOptions; |
63 |
} |
64 |
// a nullable argument is dereferenced without a check |
65 |
public void test_nullable_paramter_001() { |
66 |
runNegativeTest( |
67 |
new String[] { |
68 |
"X.java", |
69 |
"public class X {\n" + |
70 |
" void foo(@Nullable Object o) {\n" + |
71 |
" System.out.print(o.toString());\n" + |
72 |
" }\n" + |
73 |
"}\n"}, |
74 |
"----------\n" + |
75 |
"1. ERROR in X.java (at line 3)\n" + |
76 |
" System.out.print(o.toString());\n" + |
77 |
" ^\n" + |
78 |
"Potential null pointer access: The variable o may be null at this location\n" + |
79 |
"----------\n", |
80 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
81 |
} |
82 |
|
83 |
// a null value is passed to a nullable argument |
84 |
public void test_nullable_paramter_002() { |
85 |
runConformTest( |
86 |
new String[] { |
87 |
"X.java", |
88 |
"public class X {\n" + |
89 |
" void foo(@Nullable Object o) {\n" + |
90 |
" // nop\n" + |
91 |
" }\n" + |
92 |
" void bar() {\n" + |
93 |
" foo(null);\n" + |
94 |
" }\n" + |
95 |
"}\n"}, |
96 |
""); |
97 |
} |
98 |
|
99 |
// a non-null argument is checked for null |
100 |
public void test_nonnull_parameter_001() { |
101 |
runNegativeTest( |
102 |
new String[] { |
103 |
"X.java", |
104 |
"public class X {\n" + |
105 |
" void foo(@NonNull Object o) {\n" + |
106 |
" if (o != null)\n" + |
107 |
" System.out.print(o.toString());\n" + |
108 |
" }\n" + |
109 |
"}\n"}, |
110 |
"----------\n" + |
111 |
"1. ERROR in X.java (at line 3)\n" + |
112 |
" if (o != null)\n" + |
113 |
" ^\n" + |
114 |
"Redundant null check: The variable o cannot be null at this location\n" + |
115 |
"----------\n", |
116 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
117 |
} |
118 |
// a non-null argument is dereferenced without a check |
119 |
public void test_nonnull_parameter_002() { |
120 |
runConformTest( |
121 |
new String[] { |
122 |
"X.java", |
123 |
"public class X {\n" + |
124 |
" void foo(@NonNull Object o) {\n" + |
125 |
" System.out.print(o.toString());\n" + |
126 |
" }\n" + |
127 |
" public static void main(String... args) {\n" + |
128 |
" new X().foo(\"OK\");\n" + |
129 |
" }\n" + |
130 |
"}\n"}, |
131 |
"OK"); |
132 |
} |
133 |
// passing null to nonnull parameter |
134 |
public void test_nonnull_parameter_003() { |
135 |
runNegativeTest( |
136 |
new String[] { |
137 |
"X.java", |
138 |
"public class X {\n" + |
139 |
" void foo(@NonNull Object o) {\n" + |
140 |
" System.out.print(o.toString());\n" + |
141 |
" }\n" + |
142 |
" void bar() {\n" + |
143 |
" foo(null);\n" + |
144 |
" }\n" + |
145 |
"}\n"}, |
146 |
"----------\n" + |
147 |
"1. ERROR in X.java (at line 6)\n" + |
148 |
" foo(null);\n" + |
149 |
" ^^^^\n" + |
150 |
"Null contract violation: passing null to a parameter declared as @NonNull.\n" + |
151 |
"----------\n", |
152 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
153 |
} |
154 |
// passing potential null to nonnull parameter - target method is consumed from .class |
155 |
public void test_nonnull_parameter_004() { |
156 |
runConformTest( |
157 |
new String[] { |
158 |
"Lib.java", |
159 |
"public class Lib {\n" + |
160 |
" void setObject(@NonNull Object o) { }\n" + |
161 |
"}\n" |
162 |
}); |
163 |
runNegativeTest( |
164 |
false /* flush output directory */, |
165 |
new String[] { |
166 |
"X.java", |
167 |
"public class X {\n" + |
168 |
" void bar(Lib l, boolean b) {\n" + |
169 |
" Object o = null;\n" + |
170 |
" if (b) o = new Object();\n" + |
171 |
" l.setObject(o);\n" + |
172 |
" }\n" + |
173 |
"}\n"}, |
174 |
null /* no class libraries */, |
175 |
null /* no custom options */, |
176 |
"----------\n" + |
177 |
"1. ERROR in X.java (at line 5)\n" + |
178 |
" l.setObject(o);\n" + |
179 |
" ^\n" + |
180 |
"Null contract violation: potentially passing null to a parameter declared as @NonNull.\n" + |
181 |
"----------\n", |
182 |
"",/* expected output */ |
183 |
"",/* expected error */ |
184 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
185 |
} |
186 |
// passing unknown value to nonnull parameter - target method is consumed from .class |
187 |
public void test_nonnull_parameter_005() { |
188 |
runConformTest( |
189 |
new String[] { |
190 |
"Lib.java", |
191 |
"public class Lib {\n" + |
192 |
" void setObject(@NonNull Object o) { }\n" + |
193 |
"}\n" |
194 |
}); |
195 |
runConformTest( |
196 |
false /* flush output directory */, |
197 |
new String[] { |
198 |
"X.java", |
199 |
"public class X {\n" + |
200 |
" void bar(Lib l, Object o) {\n" + |
201 |
" l.setObject(o);\n" + |
202 |
" }\n" + |
203 |
"}\n"}, |
204 |
null /* no class libraries */, |
205 |
null /* no custom options */, |
206 |
"----------\n" + |
207 |
"1. WARNING in X.java (at line 3)\n" + |
208 |
" l.setObject(o);\n" + |
209 |
" ^\n" + |
210 |
"Potential null contract violation: insufficient nullness information regarding a value that is passed to a parameter declared as @NonNull.\n" + |
211 |
"----------\n", |
212 |
"",/* expected output */ |
213 |
"",/* expected error */ |
214 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
215 |
} |
216 |
// a method tries to tighten the null contract, super declares parameter o as @Nullable |
217 |
// other parameters: s is redefined from not constrained to @Nullable which is OK |
218 |
// third is redefined from not constrained to @NonNull which is bad, too |
219 |
public void test_parameter_contract_inheritance_001() { |
220 |
runConformTest( |
221 |
new String[] { |
222 |
"Lib.java", |
223 |
"public class Lib {\n" + |
224 |
" void foo(String s, @Nullable Object o, Object third) { }\n" + |
225 |
"}\n" |
226 |
}); |
227 |
runNegativeTest( |
228 |
false /* flush output directory */, |
229 |
new String[] { |
230 |
"X.java", |
231 |
"public class X extends Lib {\n" + |
232 |
" @Override\n" + |
233 |
" void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" + |
234 |
"}\n" |
235 |
}, |
236 |
// compiler options |
237 |
null /* no class libraries */, |
238 |
null /* no custom options */, |
239 |
"----------\n" + |
240 |
"1. ERROR in X.java (at line 3)\n" + |
241 |
" void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" + |
242 |
" ^\n" + |
243 |
"Cannot tighten null contract for parameter o, inherited method from Lib declares this parameter as @Nullable.\n" + |
244 |
"----------\n" + |
245 |
"2. ERROR in X.java (at line 3)\n" + |
246 |
" void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" + |
247 |
" ^^^^^\n" + |
248 |
"Cannot tighten null contract for parameter third, inherited method from Lib does not constrain this parameter.\n" + |
249 |
"----------\n", |
250 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
251 |
} |
252 |
// a method body fails to handle the inherited null contract, super declares parameter as @Nullable |
253 |
public void test_parameter_contract_inheritance_002() { |
254 |
runConformTest( |
255 |
new String[] { |
256 |
"Lib.java", |
257 |
"public class Lib {\n" + |
258 |
" void foo(@Nullable Object o) { }\n" + |
259 |
"}\n" |
260 |
}); |
261 |
runNegativeTest( |
262 |
false /* flush output directory */, |
263 |
new String[] { |
264 |
"X.java", |
265 |
"public class X extends Lib {\n" + |
266 |
" @Override\n" + |
267 |
" void foo(Object o) {\n" + |
268 |
" System.out.print(o.toString());\n" + |
269 |
" }\n" + |
270 |
"}\n" |
271 |
}, |
272 |
// compiler options |
273 |
null /* no class libraries */, |
274 |
null /* no custom options */, |
275 |
"----------\n" + |
276 |
"1. ERROR in X.java (at line 4)\n" + |
277 |
" System.out.print(o.toString());\n" + |
278 |
" ^\n" + |
279 |
"Potential null pointer access: The variable o may be null at this location\n" + |
280 |
"----------\n", |
281 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
282 |
} |
283 |
// a method relaxes the parameter null contract, super declares parameter o as @NonNull |
284 |
// other (first) parameter just repeats the inherited @NonNull |
285 |
public void test_parameter_contract_inheritance_003() { |
286 |
runConformTest( |
287 |
new String[] { |
288 |
"Lib.java", |
289 |
"public class Lib {\n" + |
290 |
" void foo(@NonNull String s, @NonNull Object o) { }\n" + |
291 |
"}\n", |
292 |
"X.java", |
293 |
"public class X extends Lib {\n" + |
294 |
" @Override\n" + |
295 |
" void foo(@NonNull String s, @Nullable Object o) { ; }\n" + |
296 |
" void bar() { foo(\"OK\", null); }\n" + |
297 |
"}\n" |
298 |
}, |
299 |
""); |
300 |
} |
301 |
// a method adds a @NonNull annotation, super has no null annotation |
302 |
// changing other from unconstrained to @Nullable is OK |
303 |
public void test_parameter_contract_inheritance_004() { |
304 |
runConformTest( |
305 |
new String[] { |
306 |
"Lib.java", |
307 |
"public class Lib {\n" + |
308 |
" void foo(Object o, Object other) { }\n" + |
309 |
"}\n" |
310 |
}); |
311 |
runNegativeTest( |
312 |
false /* flush output directory */, |
313 |
new String[] { |
314 |
"X.java", |
315 |
"public class X extends Lib {\n" + |
316 |
" @Override\n" + |
317 |
" void foo(@NonNull Object o, @Nullable Object other) { System.out.print(o.toString()); }\n" + |
318 |
"}\n" |
319 |
}, |
320 |
// compiler options |
321 |
null /* no class libraries */, |
322 |
null /* no custom options */, |
323 |
"----------\n" + |
324 |
"1. ERROR in X.java (at line 3)\n" + |
325 |
" void foo(@NonNull Object o, @Nullable Object other) { System.out.print(o.toString()); }\n" + |
326 |
" ^\n" + |
327 |
"Cannot tighten null contract for parameter o, inherited method from Lib does not constrain this parameter.\n" + |
328 |
"----------\n", |
329 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
330 |
} |
331 |
// a method tries to relax the null contract, super declares @NonNull return |
332 |
public void test_parameter_contract_inheritance_005() { |
333 |
runConformTest( |
334 |
new String[] { |
335 |
"Lib.java", |
336 |
"public class Lib {\n" + |
337 |
" @NonNull Object getObject() { return new Object(); }\n" + |
338 |
"}\n" |
339 |
}); |
340 |
runNegativeTest( |
341 |
false /* flush output directory */, |
342 |
new String[] { |
343 |
"X.java", |
344 |
"public class X extends Lib {\n" + |
345 |
" @Override\n" + |
346 |
" @Nullable Object getObject() { return null; }\n" + |
347 |
"}\n" |
348 |
}, |
349 |
// compiler options |
350 |
null /* no class libraries */, |
351 |
null /* no custom options */, |
352 |
"----------\n" + |
353 |
"1. ERROR in X.java (at line 3)\n" + |
354 |
" @Nullable Object getObject() { return null; }\n" + |
355 |
" ^^^^^^^^^^^\n" + |
356 |
"Cannot relax null contract for method return, inherited method from Lib is declared as @NonNull.\n" + |
357 |
"----------\n", |
358 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
359 |
} |
360 |
// super has no contraint for return, sub method confirms the null contract as @Nullable |
361 |
public void test_parameter_contract_inheritance_006() { |
362 |
runConformTest( |
363 |
new String[] { |
364 |
"Lib.java", |
365 |
"public class Lib {\n" + |
366 |
" Object getObject() { return null; }\n" + |
367 |
"}\n" |
368 |
}); |
369 |
runConformTest( |
370 |
new String[] { |
371 |
"X.java", |
372 |
"public class X extends Lib {\n" + |
373 |
" @Override\n" + |
374 |
" @Nullable Object getObject() { return null; }\n" + |
375 |
"}\n" |
376 |
}, |
377 |
"", |
378 |
null/*classLibs*/, |
379 |
false /* flush output directory */, |
380 |
null/*vmArguments*/, |
381 |
null/*customOptions*/, |
382 |
null/*compilerRequestor*/); |
383 |
} |
384 |
// a method body violates the inherited null contract, super declares @NonNull return |
385 |
public void test_parameter_contract_inheritance_007() { |
386 |
runConformTest( |
387 |
new String[] { |
388 |
"Lib.java", |
389 |
"public class Lib {\n" + |
390 |
" @NonNull Object getObject() { return new Object(); }\n" + |
391 |
"}\n" |
392 |
}); |
393 |
runNegativeTest( |
394 |
false /* flush output directory */, |
395 |
new String[] { |
396 |
"X.java", |
397 |
"public class X extends Lib {\n" + |
398 |
" @Override\n" + |
399 |
" Object getObject() { return null; }\n" + |
400 |
"}\n" |
401 |
}, |
402 |
// compiler options |
403 |
null /* no class libraries */, |
404 |
null /* no custom options */, |
405 |
"----------\n" + |
406 |
"1. ERROR in X.java (at line 3)\n" + |
407 |
" Object getObject() { return null; }\n" + |
408 |
" ^^^^^^^^^^^^\n" + |
409 |
"Null contract violation: returning null from a method declared as @NonNull.\n" + |
410 |
"----------\n", |
411 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
412 |
} |
413 |
// a nullable return value is dereferenced without a check |
414 |
public void test_nullable_return_001() { |
415 |
runNegativeTest( |
416 |
new String[] { |
417 |
"X.java", |
418 |
"public class X {\n" + |
419 |
" @Nullable Object getObject() { return null; }\n" + |
420 |
" void foo() {\n" + |
421 |
" Object o = getObject();\n" + |
422 |
" System.out.print(o.toString());\n" + |
423 |
" }\n" + |
424 |
"}\n" |
425 |
}, |
426 |
"----------\n" + |
427 |
"1. ERROR in X.java (at line 5)\n" + |
428 |
" System.out.print(o.toString());\n" + |
429 |
" ^\n" + |
430 |
"Potential null pointer access: The variable o may be null at this location\n" + |
431 |
"----------\n", |
432 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
433 |
} |
434 |
// a nullable return value is dereferenced without a check, method is read from .class file |
435 |
public void test_nullable_return_002() { |
436 |
runConformTest( |
437 |
new String[] { |
438 |
"Lib.java", |
439 |
"public class Lib {\n" + |
440 |
" @Nullable Object getObject() { return null; }\n" + |
441 |
"}\n" |
442 |
}); |
443 |
runNegativeTest( |
444 |
false /* flush output directory */, |
445 |
new String[] { |
446 |
"X.java", |
447 |
"public class X {\n" + |
448 |
" void foo(Lib l) {\n" + |
449 |
" Object o = l.getObject();\n" + |
450 |
" System.out.print(o.toString());\n" + |
451 |
" }\n" + |
452 |
"}\n" |
453 |
}, |
454 |
// compiler options |
455 |
null /* no class libraries */, |
456 |
null /* no custom options */, |
457 |
"----------\n" + |
458 |
"1. ERROR in X.java (at line 4)\n" + |
459 |
" System.out.print(o.toString());\n" + |
460 |
" ^\n" + |
461 |
"Potential null pointer access: The variable o may be null at this location\n" + |
462 |
"----------\n", |
463 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
464 |
} |
465 |
// a non-null return value is checked for null, method is read from .class file |
466 |
public void test_nonnull_return_001() { |
467 |
runConformTest( |
468 |
new String[] { |
469 |
"Lib.java", |
470 |
"public class Lib {\n" + |
471 |
" @NonNull Object getObject() { return new Object(); }\n" + |
472 |
"}\n" |
473 |
}); |
474 |
runNegativeTest( |
475 |
false /* flush output directory */, |
476 |
new String[] { |
477 |
"X.java", |
478 |
"public class X {\n" + |
479 |
" void foo(Lib l) {\n" + |
480 |
" Object o = l.getObject();\n" + |
481 |
" if (o != null)\n" + |
482 |
" System.out.print(o.toString());\n" + |
483 |
" }\n" + |
484 |
"}\n" |
485 |
}, |
486 |
// compiler options |
487 |
null /* no class libraries */, |
488 |
null /* no custom options */, |
489 |
"----------\n" + |
490 |
"1. ERROR in X.java (at line 4)\n" + |
491 |
" if (o != null)\n" + |
492 |
" ^\n" + |
493 |
"Redundant null check: The variable o cannot be null at this location\n" + |
494 |
"----------\n", |
495 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
496 |
} |
497 |
// a non-null method returns null |
498 |
public void test_nonnull_return_003() { |
499 |
runNegativeTest( |
500 |
new String[] { |
501 |
"X.java", |
502 |
"public class X {\n" + |
503 |
" @NonNull Object getObject(boolean b) {\n" + |
504 |
" if (b)\n" + |
505 |
" return null;\n" + // definite contract violation despite enclosing "if" |
506 |
" return new Object();\n" + |
507 |
" }\n" + |
508 |
"}\n" |
509 |
}, |
510 |
"----------\n" + |
511 |
"1. ERROR in X.java (at line 4)\n" + |
512 |
" return null;\n" + |
513 |
" ^^^^^^^^^^^^\n" + |
514 |
"Null contract violation: returning null from a method declared as @NonNull.\n" + |
515 |
"----------\n", |
516 |
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); |
517 |
} |
518 |
// a non-null method potentially returns null |
519 |
public void test_nonnull_return_004() { |
520 |
runNegativeTest( |
521 |
new String[] { |
522 |
"X.java", |
523 |
"public class X {\n" + |
524 |
" @NonNull Object getObject(@Nullable Object o) {\n" + |
525 |
" return o;\n" + // 'o' is only potentially null |
526 |
" }\n" + |
527 |
"}\n" |
528 |
}, |
529 |
"----------\n" + |
530 |
"1. ERROR in X.java (at line 3)\n" + |
531 |
" return o;\n" + |
532 |
" ^^^^^^^^^\n" + |
533 |
"Null contract violation: return value can be null but method is declared as @NonNull.\n" + |
534 |
"----------\n"); |
535 |
} |
536 |
// a non-null method returns its non-null argument |
537 |
public void test_nonnull_return_005() { |
538 |
Map customOptions = getCompilerOptions(); |
539 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
540 |
runConformTest( |
541 |
new String[] { |
542 |
"X.java", |
543 |
"public class X {\n" + |
544 |
" @NonNull Object getObject(@NonNull Object o) {\n" + |
545 |
" return o;\n" + |
546 |
" }\n" + |
547 |
"}\n" |
548 |
}, |
549 |
"", |
550 |
null/*classLibs*/, |
551 |
true/*shouldFlushOutputDirectory*/, |
552 |
null/*vmArguments*/, |
553 |
customOptions, |
554 |
null/*compilerRequestor*/); |
555 |
} |
556 |
//a non-null method has insufficient nullness info for its return value |
557 |
public void test_nonnull_return_006() { |
558 |
runNegativeTest( |
559 |
new String[] { |
560 |
"X.java", |
561 |
"public class X {\n" + |
562 |
" @NonNull Object getObject(Object o) {\n" + |
563 |
" return o;\n" + |
564 |
" }\n" + |
565 |
"}\n" |
566 |
}, |
567 |
"----------\n" + |
568 |
"1. WARNING in X.java (at line 3)\n" + |
569 |
" return o;\n" + |
570 |
" ^^^^^^^^^\n" + |
571 |
"Potential null contract violation: insufficient nullness information regarding return value while the method is declared as @NonNull.\n" + |
572 |
"----------\n"); |
573 |
} |
574 |
// mixed use of fully qualified name / explicit import |
575 |
public void test_annotation_import_001() { |
576 |
Map customOptions = getCompilerOptions(); |
577 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
578 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable"); |
579 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull"); |
580 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.DISABLED); |
581 |
runConformTest( |
582 |
new String[] { |
583 |
"Lib.java", |
584 |
"public class Lib {\n" + |
585 |
" @org.foo.NonNull Object getObject() { return new Object(); }\n" + // FQN |
586 |
"}\n", |
587 |
"X.java", |
588 |
"import org.foo.NonNull;\n" + // explicit import |
589 |
"public class X {\n" + |
590 |
" @NonNull Object getObject(@NonNull Lib l) {\n" + |
591 |
" return l.getObject();\n" + |
592 |
" }\n" + |
593 |
"}\n" |
594 |
}, |
595 |
"", |
596 |
null/*classLibs*/, |
597 |
true/*shouldFlushOutputDirectory*/, |
598 |
null/*vmArguments*/, |
599 |
customOptions, |
600 |
null/*compilerRequestor*/); |
601 |
} |
602 |
|
603 |
// use of explicit imports throughout |
604 |
public void test_annotation_import_002() { |
605 |
Map customOptions = getCompilerOptions(); |
606 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
607 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable"); |
608 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull"); |
609 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.DISABLED); |
610 |
runConformTest( |
611 |
new String[] { |
612 |
"Lib.java", |
613 |
"import org.foo.NonNull;\n" + |
614 |
"public class Lib {\n" + |
615 |
" @NonNull Object getObject() { return new Object(); }\n" + |
616 |
"}\n", |
617 |
"X.java", |
618 |
"import org.foo.NonNull;\n" + |
619 |
"public class X {\n" + |
620 |
" @NonNull Object getObject(@org.foo.Nullable String dummy, @NonNull Lib l) {\n" + |
621 |
" Object o = l.getObject();" + |
622 |
" return o;\n" + |
623 |
" }\n" + |
624 |
"}\n" |
625 |
}, |
626 |
"", |
627 |
null/*classLibs*/, |
628 |
true/*shouldFlushOutputDirectory*/, |
629 |
null/*vmArguments*/, |
630 |
customOptions, |
631 |
null/*compilerRequestor*/); |
632 |
} |
633 |
// default import plus explicit ones |
634 |
public void test_annotation_import_003() { |
635 |
Map customOptions = getCompilerOptions(); |
636 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
637 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable"); |
638 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull"); |
639 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
640 |
runConformTest( |
641 |
new String[] { |
642 |
"libpack/Lib.java", |
643 |
"package libpack;\n" + |
644 |
"public class Lib {\n" + |
645 |
" public @NonNull Object getObject() { return new Object(); }\n" + |
646 |
"}\n", |
647 |
"X.java", |
648 |
"import libpack.Lib;\n" + |
649 |
"public class X {\n" + |
650 |
" @NonNull Object getObject(@NonNull Lib l) {\n" + |
651 |
" return l.getObject();\n" + |
652 |
" }\n" + |
653 |
"}\n" |
654 |
}, |
655 |
"", |
656 |
null/*classLibs*/, |
657 |
true/*shouldFlushOutputDirectory*/, |
658 |
null/*vmArguments*/, |
659 |
customOptions, |
660 |
null/*compilerRequestor*/); |
661 |
} |
662 |
// default import but unspecified annotation names |
663 |
public void test_annotation_import_004() { |
664 |
Map customOptions = getCompilerOptions(); |
665 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
666 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, null); |
667 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, null); |
668 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
669 |
runConformTest( |
670 |
new String[] { |
671 |
"libpack/Lib.java", |
672 |
"package libpack;\n" + |
673 |
"public class Lib {\n" + |
674 |
" public @NonNull Object getObject() { return new Object(); }\n" + |
675 |
"}\n", |
676 |
"X.java", |
677 |
"import libpack.Lib;\n" + |
678 |
"public class X {\n" + |
679 |
" @NonNull Object getObject(@NonNull Lib l) {\n" + |
680 |
" return l.getObject();\n" + |
681 |
" }\n" + |
682 |
"}\n" |
683 |
}, |
684 |
"", |
685 |
null/*classLibs*/, |
686 |
true/*shouldFlushOutputDirectory*/, |
687 |
null/*vmArguments*/, |
688 |
customOptions, |
689 |
null/*compilerRequestor*/); |
690 |
} |
691 |
// default import of existing annotation types |
692 |
public void test_annotation_import_005() { |
693 |
Map customOptions = getCompilerOptions(); |
694 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
695 |
customOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.ERROR); |
696 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull"); |
697 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull"); |
698 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
699 |
customOptions.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.DISABLED); |
700 |
runNegativeTest( |
701 |
true/*shouldFlushOutputDirectory*/, |
702 |
new String[] { |
703 |
"Lib.java", |
704 |
"public class Lib {\n" + |
705 |
" Object getObject() { return new Object(); }\n" + |
706 |
"}\n", |
707 |
"X.java", |
708 |
"public class X {\n" + |
709 |
" @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" + |
710 |
" return l.getObject();\n" + |
711 |
" }\n" + |
712 |
"}\n", |
713 |
|
714 |
"org/foo/MayBeNull.java", |
715 |
"package org.foo;\n" + |
716 |
"import java.lang.annotation.*;\n" + |
717 |
"@Retention(RetentionPolicy.CLASS)\n" + |
718 |
"public @interface MayBeNull {}\n", |
719 |
|
720 |
"org/foo/MustNotBeNull.java", |
721 |
"package org.foo;\n" + |
722 |
"import java.lang.annotation.*;\n" + |
723 |
"@Retention(RetentionPolicy.CLASS)\n" + |
724 |
"public @interface MustNotBeNull {}\n", |
725 |
}, |
726 |
null/*classLibs*/, |
727 |
customOptions, |
728 |
"----------\n" + |
729 |
"1. ERROR in X.java (at line 3)\n" + |
730 |
" return l.getObject();\n" + |
731 |
" ^^^^^^^^^^^^^^^^^^^^^\n" + |
732 |
"Potential null contract violation: insufficient nullness information regarding return value while the method is declared as @MustNotBeNull.\n" + |
733 |
// "Potential null contract violation: insufficient nullness information for checking return value against declaration as @MustNotBeNull.\n" + |
734 |
"----------\n", |
735 |
JavacTestOptions.SKIP); |
736 |
} |
737 |
// a non-null method returns a value obtained from an unannotated method, default import of missing annotation types |
738 |
public void test_annotation_import_006() { |
739 |
Map customOptions = getCompilerOptions(); |
740 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
741 |
customOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.ERROR); |
742 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull"); |
743 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull"); |
744 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
745 |
customOptions.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.DISABLED); |
746 |
runNegativeTest( |
747 |
true/*shouldFlushOutputDirectory*/, |
748 |
new String[] { |
749 |
"Lib.java", |
750 |
"public class Lib {\n" + |
751 |
" Object getObject() { return new Object(); }\n" + |
752 |
"}\n", |
753 |
"X.java", |
754 |
"public class X {\n" + |
755 |
" @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" + |
756 |
" return l.getObject();\n" + |
757 |
" }\n" + |
758 |
"}\n" |
759 |
}, |
760 |
null/*classLibs*/, |
761 |
customOptions, |
762 |
"----------\n" + |
763 |
"1. ERROR in Lib.java (at line 0)\n" + |
764 |
" public class Lib {\n" + |
765 |
" ^\n" + |
766 |
"Buildpath problem: the type org.foo.MayBeNull which is configured as a null annotation type cannot be resolved.\n" + |
767 |
"----------\n", |
768 |
JavacTestOptions.SKIP); |
769 |
} |
770 |
// emulation names conflict with existing types |
771 |
public void test_annotation_emulation_001() { |
772 |
Map customOptions = getCompilerOptions(); |
773 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
774 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "libpack.Lib"); |
775 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "libpack.Lib"); |
776 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED); |
777 |
runNegativeTest( |
778 |
true/*shouldFlushOutputDirectory*/, |
779 |
new String[] { |
780 |
"libpack/Lib.java", |
781 |
"package libpack;\n" + |
782 |
"public class Lib {\n" + |
783 |
"}\n", |
784 |
}, |
785 |
null/*classLibs*/, |
786 |
customOptions, |
787 |
"----------\n" + |
788 |
"1. ERROR in libpack\\Lib.java (at line 0)\n" + |
789 |
" package libpack;\n" + |
790 |
" ^\n" + |
791 |
"Buildpath problem: emulation of type libpack.Lib is requested (for null annotations) but a type of this name exists on the build path.\n" + |
792 |
"----------\n", |
793 |
JavacTestOptions.SKIP); |
794 |
} |
795 |
// regular use (explicit import/FQN) of existing annotation types (=no emulation) |
796 |
public void test_annotation_emulation_002() { |
797 |
Map customOptions = getCompilerOptions(); |
798 |
customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR); |
799 |
customOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.ERROR); |
800 |
customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull"); |
801 |
customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull"); |
802 |
customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.DISABLED); |
803 |
customOptions.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.DISABLED); |
804 |
runNegativeTest( |
805 |
true/*shouldFlushOutputDirectory*/, |
806 |
new String[] { |
807 |
"Lib.java", |
808 |
"public class Lib {\n" + |
809 |
" @org.foo.MayBeNull Object getObject() { return new Object(); }\n" + // FQN |
810 |
"}\n", |
811 |
"X.java", |
812 |
"import org.foo.MustNotBeNull;\n" + // explicit import |
813 |
"public class X {\n" + |
814 |
" @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" + |
815 |
" return l.getObject();\n" + |
816 |
" }\n" + |
817 |
"}\n", |
818 |
|
819 |
"org/foo/MayBeNull.java", |
820 |
"package org.foo;\n" + |
821 |
"import java.lang.annotation.*;\n" + |
822 |
"@Retention(RetentionPolicy.CLASS)\n" + |
823 |
"public @interface MayBeNull {}\n", |
824 |
|
825 |
"org/foo/MustNotBeNull.java", |
826 |
"package org.foo;\n" + |
827 |
"import java.lang.annotation.*;\n" + |
828 |
"@Retention(RetentionPolicy.CLASS)\n" + |
829 |
"public @interface MustNotBeNull {}\n", |
830 |
}, |
831 |
null/*classLibs*/, |
832 |
customOptions, |
833 |
"----------\n" + |
834 |
"1. ERROR in X.java (at line 4)\n" + |
835 |
" return l.getObject();\n" + |
836 |
" ^^^^^^^^^^^^^^^^^^^^^\n" + |
837 |
"Null contract violation: return value can be null but method is declared as @MustNotBeNull.\n" + |
838 |
"----------\n", |
839 |
JavacTestOptions.SKIP); |
840 |
} |
841 |
|
842 |
} |