View | Details | Raw Unified | Return to bug 186342 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java (-1 / +11 lines)
Lines 14-19 Link Here
14
 *     							bug 185682 - Increment/decrement operators mark local variables as read
14
 *     							bug 185682 - Increment/decrement operators mark local variables as read
15
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
16
 *     							bug 359721 - [options] add command line option for new warning token "resource"
16
 *     							bug 359721 - [options] add command line option for new warning token "resource"
17
 *     							bug 186342 - [compiler][null] Using annotations for null checking
17
 *******************************************************************************/
18
 *******************************************************************************/
18
package org.eclipse.jdt.core.tests.compiler.regression;
19
package org.eclipse.jdt.core.tests.compiler.regression;
19
20
Lines 1799-1804 Link Here
1799
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1800
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1800
			"	</command_line>\n" + 
1801
			"	</command_line>\n" + 
1801
			"	<options>\n" + 
1802
			"	<options>\n" + 
1803
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnull\" value=\"org.eclipse.jdt.annotation.NonNull\"/>\n" +
1804
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullbydefault\" value=\"org.eclipse.jdt.annotation.NonNullByDefault\"/>\n" +
1805
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nonnullisdefault\" value=\"disabled\"/>\n" +
1806
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullable\" value=\"org.eclipse.jdt.annotation.Nullable\"/>\n" +
1807
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.nullanalysis\" value=\"disabled\"/>\n" +
1802
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"disabled\"/>\n" + 
1808
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"disabled\"/>\n" + 
1803
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.5\"/>\n" + 
1809
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.5\"/>\n" + 
1804
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
1810
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
Lines 1857-1870 Link Here
1857
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" + 
1863
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" + 
1858
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
1864
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
1859
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" + 
1865
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" + 
1860
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" + 
1866
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" +
1867
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo\" value=\"warning\"/>\n" +
1868
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecViolation\" value=\"error\"/>\n" +
1861
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
1869
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
1862
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
1870
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
1863
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1871
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1864
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1872
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1865
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1873
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1874
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation\" value=\"error\"/>\n" +
1866
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" +
1875
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" +
1867
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" +
1876
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" +
1877
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation\" value=\"warning\"/>\n" +
1868
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
1878
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
1869
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments\" value=\"ignore\"/>\n" + 
1879
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments\" value=\"ignore\"/>\n" + 
1870
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSuperinterface\" value=\"ignore\"/>\n" + 
1880
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantSuperinterface\" value=\"ignore\"/>\n" + 
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java (+29 lines)
Lines 11-16 Link Here
11
 *     Stephan Herrmann  - Contributions for 
11
 *     Stephan Herrmann  - Contributions for 
12
 *     							bug 236385: [compiler] Warn for potential programming problem if an object is created but not used
12
 *     							bug 236385: [compiler] Warn for potential programming problem if an object is created but not used
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     							bug 186342 - [compiler][null] Using annotations for null checking
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.core.tests.compiler.regression;
16
package org.eclipse.jdt.core.tests.compiler.regression;
16
17
Lines 380-385 Link Here
380
		expectedProblemAttributes.put("CannotDefineStaticInitializerInLocalType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
381
		expectedProblemAttributes.put("CannotDefineStaticInitializerInLocalType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
381
		expectedProblemAttributes.put("CannotExtendEnum", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
382
		expectedProblemAttributes.put("CannotExtendEnum", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
382
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
383
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
384
		expectedProblemAttributes.put("CannotImplementIncompatibleNullness", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
383
		expectedProblemAttributes.put("CannotImportPackage", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
385
		expectedProblemAttributes.put("CannotImportPackage", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
384
		expectedProblemAttributes.put("CannotInferElidedTypes", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
386
		expectedProblemAttributes.put("CannotInferElidedTypes", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
385
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
387
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 470-477 Link Here
470
		expectedProblemAttributes.put("HierarchyHasProblems", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
472
		expectedProblemAttributes.put("HierarchyHasProblems", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
471
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
473
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
472
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
474
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
475
		expectedProblemAttributes.put("IllegalAnnotationForBaseType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
473
		expectedProblemAttributes.put("IllegalCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
476
		expectedProblemAttributes.put("IllegalCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
474
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
477
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
478
		expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
475
		expectedProblemAttributes.put("IllegalDimension", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
479
		expectedProblemAttributes.put("IllegalDimension", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
476
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
480
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
477
		expectedProblemAttributes.put("IllegalExtendedDimensions", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
481
		expectedProblemAttributes.put("IllegalExtendedDimensions", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 506-511 Link Here
506
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
510
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
507
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
511
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
508
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
512
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
513
		expectedProblemAttributes.put("IllegalReturnNullityRedefinition", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
514
		expectedProblemAttributes.put("IllegalRedefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
509
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
515
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
510
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
516
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
511
		expectedProblemAttributes.put("IllegalUnderscorePosition", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
517
		expectedProblemAttributes.put("IllegalUnderscorePosition", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
Lines 690-695 Link Here
690
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
696
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
691
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
697
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
692
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
698
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
699
		expectedProblemAttributes.put("MissingNullAnnotationType", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
693
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
700
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
694
		expectedProblemAttributes.put("MissingReturnType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
701
		expectedProblemAttributes.put("MissingReturnType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
695
		expectedProblemAttributes.put("MissingSemiColon", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
702
		expectedProblemAttributes.put("MissingSemiColon", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
Lines 745-750 Link Here
745
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
752
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
746
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
753
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
747
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
754
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
755
		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
756
		expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
748
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
757
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
749
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
758
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
750
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
759
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
Lines 771-776 Link Here
771
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
780
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
772
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
781
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
773
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
782
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
783
		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
774
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
784
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
775
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
785
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
776
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
786
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
Lines 779-788 Link Here
779
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
789
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
780
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
790
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
781
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
791
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
792
		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
782
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
793
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
794
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
783
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
795
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
784
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
796
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
785
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
797
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
798
		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
799
		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
800
		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
786
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
801
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
787
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
802
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
788
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
803
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
Lines 1057-1062 Link Here
1057
		expectedProblemAttributes.put("CannotExtendEnum", SKIP);
1072
		expectedProblemAttributes.put("CannotExtendEnum", SKIP);
1058
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", SKIP);
1073
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", SKIP);
1059
		expectedProblemAttributes.put("CannotImportPackage", SKIP);
1074
		expectedProblemAttributes.put("CannotImportPackage", SKIP);
1075
		expectedProblemAttributes.put("CannotImplementIncompatibleNullness", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1060
		expectedProblemAttributes.put("CannotInferElidedTypes", SKIP);
1076
		expectedProblemAttributes.put("CannotInferElidedTypes", SKIP);
1061
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", SKIP);
1077
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", SKIP);
1062
		expectedProblemAttributes.put("CannotOverrideAStaticMethodWithAnInstanceMethod", SKIP);
1078
		expectedProblemAttributes.put("CannotOverrideAStaticMethodWithAnInstanceMethod", SKIP);
Lines 1146-1153 Link Here
1146
		expectedProblemAttributes.put("HierarchyHasProblems", SKIP);
1162
		expectedProblemAttributes.put("HierarchyHasProblems", SKIP);
1147
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", SKIP);
1163
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", SKIP);
1148
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", SKIP);
1164
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", SKIP);
1165
		expectedProblemAttributes.put("IllegalAnnotationForBaseType", SKIP);
1149
		expectedProblemAttributes.put("IllegalCast", SKIP);
1166
		expectedProblemAttributes.put("IllegalCast", SKIP);
1150
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", SKIP);
1167
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", SKIP);
1168
		expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1151
		expectedProblemAttributes.put("IllegalDimension", SKIP);
1169
		expectedProblemAttributes.put("IllegalDimension", SKIP);
1152
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", SKIP);
1170
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", SKIP);
1153
		expectedProblemAttributes.put("IllegalExtendedDimensions", SKIP);
1171
		expectedProblemAttributes.put("IllegalExtendedDimensions", SKIP);
Lines 1182-1187 Link Here
1182
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1200
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1183
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1201
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1184
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", SKIP);
1202
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", SKIP);
1203
		expectedProblemAttributes.put("IllegalRedefinitionToNonNullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1204
		expectedProblemAttributes.put("IllegalReturnNullityRedefinition", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1185
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1205
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1186
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1206
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1187
		expectedProblemAttributes.put("IllegalUnderscorePosition", SKIP);
1207
		expectedProblemAttributes.put("IllegalUnderscorePosition", SKIP);
Lines 1365-1370 Link Here
1365
		expectedProblemAttributes.put("MissingEnclosingInstance", SKIP);
1385
		expectedProblemAttributes.put("MissingEnclosingInstance", SKIP);
1366
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", SKIP);
1386
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", SKIP);
1367
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(JavaCore.COMPILER_PB_INCOMPLETE_ENUM_SWITCH));
1387
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(JavaCore.COMPILER_PB_INCOMPLETE_ENUM_SWITCH));
1388
		expectedProblemAttributes.put("MissingNullAnnotationType", SKIP);
1368
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1389
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1369
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1390
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1370
		expectedProblemAttributes.put("MissingReturnType", SKIP);
1391
		expectedProblemAttributes.put("MissingReturnType", SKIP);
Lines 1421-1426 Link Here
1421
		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
1442
		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
1422
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
1443
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
1423
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
1444
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
1445
		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1446
		expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1424
		expectedProblemAttributes.put("ParameterMismatch", SKIP);
1447
		expectedProblemAttributes.put("ParameterMismatch", SKIP);
1425
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", SKIP);
1448
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", SKIP);
1426
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", SKIP);
1449
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", SKIP);
Lines 1447-1452 Link Here
1447
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1470
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1448
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1471
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1449
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1472
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1473
		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1450
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1474
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1451
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1475
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1452
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
1476
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
Lines 1455-1465 Link Here
1455
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1479
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1456
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
1480
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
1457
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1481
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1482
		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
1458
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1483
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1484
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1459
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1485
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1460
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1486
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1461
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
1487
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
1462
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
1488
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
1489
		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1490
		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION));
1491
		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO));
1463
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", SKIP);
1492
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", SKIP);
1464
		expectedProblemAttributes.put("ReturnTypeAmbiguous", SKIP);
1493
		expectedProblemAttributes.put("ReturnTypeAmbiguous", SKIP);
1465
		expectedProblemAttributes.put("ReturnTypeCannotBeVoidArray", SKIP);
1494
		expectedProblemAttributes.put("ReturnTypeCannotBeVoidArray", SKIP);
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java (+2214 lines)
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
14
import java.io.File;
15
import java.util.Map;
16
17
import junit.framework.Test;
18
19
import org.eclipse.core.runtime.FileLocator;
20
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.jdt.core.JavaCore;
22
23
// see bug 186342 - [compiler][null] Using annotations for null checking
24
public class NullAnnotationTest extends AbstractComparableTest {
25
26
// class libraries including our default null annotation types:
27
String[] LIBS;
28
29
// names and content of custom annotations used in a few tests:
30
private static final String CUSTOM_NONNULL_NAME = "org/foo/NonNull.java";
31
private static final String CUSTOM_NONNULL_CONTENT =
32
	"package org.foo;\n" +
33
	"import static java.lang.annotation.ElementType.*;\n" +
34
	"import java.lang.annotation.*;\n" +
35
	"@Retention(RetentionPolicy.CLASS)\n" +
36
	"@Target({METHOD,PARAMETER,LOCAL_VARIABLE})\n" +
37
	"public @interface NonNull {\n" +
38
	"}\n";
39
private static final String CUSTOM_NULLABLE_NAME = "org/foo/Nullable.java";
40
private static final String CUSTOM_NULLABLE_CONTENT = "package org.foo;\n" +
41
	"import static java.lang.annotation.ElementType.*;\n" +
42
	"import java.lang.annotation.*;\n" +
43
	"@Retention(RetentionPolicy.CLASS)\n" +
44
	"@Target({METHOD,PARAMETER,LOCAL_VARIABLE})\n" +
45
	"public @interface Nullable {\n" +
46
	"}\n";
47
48
public NullAnnotationTest(String name) {
49
	super(name);
50
}
51
52
// Static initializer to specify tests subset using TESTS_* static variables
53
// All specified tests which do not belong to the class are skipped...
54
static {
55
//		TESTS_NAMES = new String[] { "test_illegal_annotation_00" };
56
//		TESTS_NUMBERS = new int[] { 561 };
57
//		TESTS_RANGE = new int[] { 1, 2049 };
58
}
59
60
public static Test suite() {
61
	return buildComparableTestSuite(testClass());
62
}
63
64
public static Class testClass() {
65
	return NullAnnotationTest.class;
66
}
67
68
protected void setUp() throws Exception {
69
	super.setUp();
70
	if (this.LIBS == null) {
71
		String[] defaultLibs = getDefaultClassPaths();
72
		int len = defaultLibs.length;
73
		this.LIBS = new String[len+1];
74
		System.arraycopy(defaultLibs, 0, this.LIBS, 0, len);
75
		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation.null"));
76
		if (bundleFile.isDirectory())
77
			this.LIBS[len] = bundleFile.getPath()+"/bin";
78
		else
79
			this.LIBS[len] = bundleFile.getPath();
80
	}
81
}
82
// Conditionally augment problem detection settings
83
static boolean setNullRelatedOptions = true;
84
protected Map getCompilerOptions() {
85
    Map defaultOptions = super.getCompilerOptions();
86
    if (setNullRelatedOptions) {
87
    	defaultOptions.put(JavaCore.COMPILER_PB_NULL_REFERENCE, JavaCore.ERROR);
88
	    defaultOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
89
	    defaultOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.ERROR);
90
		defaultOptions.put(JavaCore.COMPILER_PB_INCLUDE_ASSERTS_IN_NULL_ANALYSIS, JavaCore.ENABLED);
91
92
		defaultOptions.put(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION_FOR_INTERFACE_METHOD_IMPLEMENTATION, JavaCore.DISABLED);
93
94
		// enable null annotations:
95
		defaultOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
96
		// leave other new options at these defaults:
97
//		defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, JavaCore.ERROR);
98
//		defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, JavaCore.ERROR);
99
//		defaultOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.WARNING);
100
101
//		defaultOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.eclipse.jdt.annotation.Nullable");
102
//		defaultOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.eclipse.jdt.annotation.NonNull");
103
    }
104
    return defaultOptions;
105
}
106
void runNegativeTestWithLibs(String[] testFiles, String expectedErrorLog) {
107
	runNegativeTest(
108
			testFiles,
109
			expectedErrorLog,
110
			this.LIBS,
111
			false /*shouldFlush*/);
112
}
113
void runNegativeTestWithLibs(boolean shouldFlushOutputDirectory, String[] testFiles, Map customOptions, String expectedErrorLog) {
114
	runNegativeTest(
115
			shouldFlushOutputDirectory,
116
			testFiles,
117
			this.LIBS,
118
			customOptions,
119
			expectedErrorLog,
120
			// runtime options
121
		    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
122
}
123
void runNegativeTestWithLibs(String[] testFiles, Map customOptions, String expectedErrorLog) {
124
	runNegativeTestWithLibs(false /* flush output directory */,	testFiles, customOptions, expectedErrorLog);
125
}
126
void runConformTestWithLibs(String[] testFiles, Map customOptions, String expectedCompilerLog) {
127
	runConformTestWithLibs(false /* flush output directory */, testFiles, customOptions, expectedCompilerLog);
128
}
129
void runConformTestWithLibs(boolean shouldFlushOutputDirectory, String[] testFiles, Map customOptions, String expectedCompilerLog) {
130
	runConformTest(
131
			shouldFlushOutputDirectory,
132
			testFiles,
133
			this.LIBS,
134
			customOptions,
135
			expectedCompilerLog,
136
			"",/* expected output */
137
			"",/* expected error */
138
		    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
139
}
140
void runConformTest(String[] testFiles, Map customOptions, String expectedOutputString) {
141
	runConformTest(
142
			testFiles,
143
			expectedOutputString,
144
			null /*classLibraries*/,
145
			true /*shouldFlushOutputDirectory*/,
146
			null /*vmArguments*/,
147
			customOptions,
148
			null /*customRequestor*/);
149
150
}
151
// a nullable argument is dereferenced without a check
152
public void test_nullable_paramter_001() {
153
	runNegativeTest(
154
		new String[] {
155
			"X.java",
156
			  "import org.eclipse.jdt.annotation.*;\n" +
157
			  "public class X {\n" +
158
			  "    void foo(@Nullable Object o) {\n" +
159
			  "        System.out.print(o.toString());\n" +
160
			  "    }\n" +
161
			  "}\n"},
162
	    "----------\n" +
163
		"1. ERROR in X.java (at line 4)\n" +
164
		"	System.out.print(o.toString());\n" +
165
		"	                 ^\n" +
166
		"Potential null pointer access: The variable o may be null at this location\n" +
167
		"----------\n",
168
		this.LIBS,
169
		true /* shouldFlush*/);
170
}
171
172
// a null value is passed to a nullable argument
173
public void test_nullable_paramter_002() {
174
	runConformTest(
175
		new String[] {
176
			"X.java",
177
			  "import org.eclipse.jdt.annotation.*;\n" +
178
			  "public class X {\n" +
179
			  "    void foo(@Nullable Object o) {\n" +
180
			  "        // nop\n" +
181
			  "    }\n" +
182
			  "    void bar() {\n" +
183
			  "        foo(null);\n" +
184
			  "    }\n" +
185
			  "}\n"},
186
	    "",
187
	    this.LIBS,
188
	    false/*shouldFlush*/,
189
	    null/*vmArgs*/);
190
}
191
192
// a non-null argument is checked for null
193
public void test_nonnull_parameter_001() {
194
	runNegativeTest(
195
		new String[] {
196
			"X.java",
197
			  "import org.eclipse.jdt.annotation.*;\n" +
198
			  "public class X {\n" +
199
			  "    void foo(@NonNull Object o) {\n" +
200
			  "        if (o != null)\n" +
201
			  "              System.out.print(o.toString());\n" +
202
			  "    }\n" +
203
			  "}\n"},
204
	    "----------\n" +
205
		"1. ERROR in X.java (at line 4)\n" +
206
		"	if (o != null)\n" +
207
		"	    ^\n" +
208
		"Redundant null check: The variable o cannot be null at this location\n" +
209
		"----------\n",
210
		this.LIBS,
211
		true /* shouldFlush*/);
212
}
213
// a non-null argument is dereferenced without a check
214
public void test_nonnull_parameter_002() {
215
	runConformTest(
216
		new String[] {
217
			"X.java",
218
			  "import org.eclipse.jdt.annotation.*;\n" +
219
			  "public class X {\n" +
220
			  "    void foo(@NonNull Object o) {\n" +
221
			  "        System.out.print(o.toString());\n" +
222
			  "    }\n" +
223
			  "    public static void main(String... args) {\n" +
224
			  "        new X().foo(\"OK\");\n" +
225
			  "    }\n" +
226
			  "}\n"},
227
	    "OK",
228
	    this.LIBS,
229
	    false/*shouldFlush*/,
230
	    null/*vmArgs*/);
231
}
232
// passing null to nonnull parameter - many fields in enclosing class
233
public void test_nonnull_parameter_003() {
234
	runNegativeTest(
235
		new String[] {
236
			"X.java",
237
			  "import org.eclipse.jdt.annotation.*;\n" +
238
			  "public class X {\n" +
239
			  "    int i00, i01, i02, i03, i04, i05, i06, i07, i08, i09;" +
240
			  "    int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;" +
241
			  "    int i20, i21, i22, i23, i24, i25, i26, i27, i28, i29;" +
242
			  "    int i30, i31, i32, i33, i34, i35, i36, i37, i38, i39;" +
243
			  "    int i40, i41, i42, i43, i44, i45, i46, i47, i48, i49;" +
244
			  "    int i50, i51, i52, i53, i54, i55, i56, i57, i58, i59;" +
245
			  "    int i60, i61, i62, i63, i64, i65, i66, i67, i68, i69;" +
246
			  "    void foo(@NonNull Object o) {\n" +
247
			  "        System.out.print(o.toString());\n" +
248
			  "    }\n" +
249
			  "    void bar() {\n" +
250
			  "        foo(null);\n" +
251
			  "    }\n" +
252
			  "}\n"},
253
		"----------\n" +
254
		"1. ERROR in X.java (at line 7)\n" +
255
		"	foo(null);\n" +
256
		"	    ^^^^\n" +
257
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
258
		"----------\n",
259
		this.LIBS,
260
		true /* shouldFlush*/);
261
}
262
// passing potential null to nonnull parameter - target method is consumed from .class
263
public void test_nonnull_parameter_004() {
264
	runConformTestWithLibs(
265
			new String[] {
266
				"Lib.java",
267
					"import org.eclipse.jdt.annotation.*;\n" +
268
				"public class Lib {\n" +
269
				"    void setObject(@NonNull Object o) { }\n" +
270
				"}\n"
271
			},
272
			null /*customOptions*/,
273
			"");
274
	runNegativeTestWithLibs(
275
		false, // don't flush
276
		new String[] {
277
			"X.java",
278
			  "public class X {\n" +
279
			  "    void bar(Lib l, boolean b) {\n" +
280
			  "        Object o = null;\n" +
281
			  "        if (b) o = new Object();\n" +
282
			  "        l.setObject(o);\n" +
283
			  "    }\n" +
284
			  "}\n"},
285
		null /*customOptions*/,
286
		"----------\n" +
287
		"1. ERROR in X.java (at line 5)\n" +
288
		"	l.setObject(o);\n" +
289
		"	            ^\n" +
290
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
291
		"----------\n");
292
}
293
// passing unknown value to nonnull parameter  - target method is consumed from .class
294
public void test_nonnull_parameter_005() {
295
	runConformTestWithLibs(
296
			new String[] {
297
				"Lib.java",
298
				"import org.eclipse.jdt.annotation.*;\n" +
299
				"public class Lib {\n" +
300
				"    void setObject(@NonNull Object o) { }\n" +
301
				"}\n"
302
			},
303
			null /*customOptions*/,
304
			"");
305
	runConformTestWithLibs(
306
		false, // don't flush
307
		new String[] {
308
			"X.java",
309
			  "public class X {\n" +
310
			  "    void bar(Lib l, Object o) {\n" +
311
			  "        l.setObject(o);\n" +
312
			  "    }\n" +
313
			  "}\n"},
314
		null /* options */,
315
		"----------\n" +
316
		"1. WARNING in X.java (at line 3)\n" +
317
		"	l.setObject(o);\n" +
318
		"	            ^\n" +
319
		"Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown\n" +
320
		"----------\n");
321
}
322
// a ternary non-null expression is passed to a nonnull parameter
323
public void test_nonnull_parameter_006() {
324
	Map customOptions = getCompilerOptions();
325
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
326
	runConformTestWithLibs(
327
		new String[] {
328
			"X.java",
329
			  "import org.eclipse.jdt.annotation.*;\n" +
330
			  "public class X {\n" +
331
			  "    	void m1(@NonNull String a) {}\n" +
332
			  "		void m2(@Nullable String b) {\n" +
333
			  "			m1(b == null ? \"\" : b);\n" +
334
			  "		}\n" +
335
			  "}\n"},
336
		customOptions,
337
		""  /* compiler output */);
338
}
339
// nullable value passed to a non-null parameter in a super-call
340
public void test_nonnull_parameter_007() {
341
	Map customOptions = getCompilerOptions();
342
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
343
	runNegativeTestWithLibs(
344
		new String[] {
345
			"XSub.java",
346
			  "import org.eclipse.jdt.annotation.*;\n" +
347
			  "public class XSub extends XSuper {\n" +
348
			  "    	XSub(@Nullable String b) {\n" +
349
			  "			super(b);\n" +
350
			  "		}\n" +
351
			  "}\n",
352
			"XSuper.java",
353
			  "import org.eclipse.jdt.annotation.*;\n" +
354
			  "public class XSuper {\n" +
355
			  "    	XSuper(@NonNull String b) {\n" +
356
			  "		}\n" +
357
			  "}\n"
358
		},
359
		customOptions,
360
		"----------\n" +
361
		"1. ERROR in XSub.java (at line 4)\n" +
362
		"	super(b);\n" +
363
		"	      ^\n" +
364
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
365
		"----------\n");
366
}
367
// a nullable value is passed to a non-null parameter in an allocation expression
368
public void test_nonnull_parameter_008() {
369
	Map customOptions = getCompilerOptions();
370
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
371
	runNegativeTestWithLibs(
372
		new String[] {
373
			"X.java",
374
			  "import org.eclipse.jdt.annotation.*;\n" +
375
			  "public class X {\n" +
376
			  "    	X(@NonNull String a) {}\n" +
377
			  "		static X create(@Nullable String b) {\n" +
378
			  "			return new X(b);\n" +
379
			  "		}\n" +
380
			  "}\n"},
381
		customOptions,
382
		"----------\n" +
383
		"1. ERROR in X.java (at line 5)\n" +
384
		"	return new X(b);\n" +
385
		"	             ^\n" +
386
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
387
		"----------\n"  /* compiler output */);
388
}
389
// a nullable value is passed to a non-null parameter in a qualified allocation expression
390
public void test_nonnull_parameter_009() {
391
	Map customOptions = getCompilerOptions();
392
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
393
	runNegativeTestWithLibs(
394
		new String[] {
395
			"X.java",
396
			  "import org.eclipse.jdt.annotation.*;\n" +
397
			  "public class X {\n" +
398
			  "    class Local {\n" +
399
			  "    	   Local(@NonNull String a) {}\n" +
400
			  "    }\n" +
401
			  "	   Local create(@Nullable String b) {\n" +
402
			  "	       return this.new Local(b);\n" +
403
			  "    }\n" +
404
			  "}\n"},
405
		customOptions,
406
		"----------\n" +
407
		"1. ERROR in X.java (at line 7)\n" +
408
		"	return this.new Local(b);\n" +
409
		"	                      ^\n" +
410
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
411
		"----------\n"  /* compiler output */);
412
}
413
// assigning potential null to a nonnull local variable
414
public void test_nonnull_local_001() {
415
	runNegativeTest(
416
		new String[] {
417
			"X.java",
418
			  "import org.eclipse.jdt.annotation.*;\n" +
419
			  "public class X {\n" +
420
			  "    void foo(boolean b, Object p) {\n" +
421
			  "        @NonNull Object o1 = b ? null : new Object();\n" +
422
			  "        @NonNull String o2 = \"\";\n" +
423
			  "        o2 = null;\n" +
424
			  "        @NonNull Object o3 = p;\n" +
425
			  "    }\n" +
426
			  "}\n"},
427
		"----------\n" +
428
		"1. ERROR in X.java (at line 4)\n" +
429
		"	@NonNull Object o1 = b ? null : new Object();\n" +
430
		"	                     ^^^^^^^^^^^^^^^^^^^^^^^\n" +
431
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
432
		"----------\n" +
433
		"2. ERROR in X.java (at line 6)\n" +
434
		"	o2 = null;\n" +
435
		"	     ^^^^\n" +
436
		"Type mismatch: required \'@NonNull String\' but the provided value is null\n" +
437
		"----------\n" +
438
		"3. WARNING in X.java (at line 7)\n" +
439
		"	@NonNull Object o3 = p;\n" +
440
		"	                     ^\n" +
441
		"Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown\n" +
442
		"----------\n",
443
		this.LIBS,
444
		true /* shouldFlush*/);
445
}
446
447
// a method tries to tighten the type specification, super declares parameter o as @Nullable
448
// other parameters: s is redefined from not constrained to @Nullable which is OK
449
//                   third is redefined from not constrained to @NonNull which is bad, too
450
public void test_parameter_specification_inheritance_001() {
451
	runConformTestWithLibs(
452
		new String[] {
453
			"Lib.java",
454
			"import org.eclipse.jdt.annotation.*;\n" +
455
			"public class Lib {\n" +
456
			"    void foo(String s, @Nullable Object o, Object third) { }\n" +
457
			"}\n"
458
		},
459
		null /*customOptions*/,
460
		"");
461
	runNegativeTestWithLibs(
462
		false, // don't flush
463
		new String[] {
464
			"X.java",
465
			"import org.eclipse.jdt.annotation.*;\n" +
466
			"public class X extends Lib {\n" +
467
			"    @Override\n" +
468
			"    void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" +
469
			"}\n"
470
		},
471
		null /*customOptions*/,
472
		"----------\n" +
473
		"1. ERROR in X.java (at line 4)\n" +
474
		"	void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" +
475
		"	                             ^^^^^^^^^^^^^^^\n" +
476
		"Illegal redefinition of parameter o, inherited method from Lib declares this parameter as @Nullable\n" +
477
		"----------\n" +
478
		"2. ERROR in X.java (at line 4)\n" +
479
		"	void foo(@Nullable String s, @NonNull Object o, @NonNull Object third) { System.out.print(o.toString()); }\n" +
480
		"	                                                ^^^^^^^^^^^^^^^\n" +
481
		"Illegal redefinition of parameter third, inherited method from Lib does not constrain this parameter\n" +
482
		"----------\n");
483
}
484
// a method body fails to redeclare the inherited null annotation, super declares parameter as @Nullable
485
public void test_parameter_specification_inheritance_002() {
486
	runConformTest(
487
		new String[] {
488
			"Lib.java",
489
			"import org.eclipse.jdt.annotation.*;\n" +
490
			"public class Lib {\n" +
491
			"    void foo(@Nullable Object o) { }\n" +
492
			"}\n"
493
		},
494
		"",
495
	    this.LIBS,
496
	    false/*shouldFlush*/,
497
	    null/*vmArgs*/);
498
	runNegativeTestWithLibs(
499
		false, // don't flush
500
		new String[] {
501
			"X.java",
502
			"public class X extends Lib {\n" +
503
			"    @Override\n" +
504
			"    void foo(Object o) {\n" +
505
			"        System.out.print(o.toString());\n" +
506
			"    }\n" +
507
			"}\n"
508
		},
509
		null /*customOptions*/,
510
		"----------\n" +
511
		"1. ERROR in X.java (at line 3)\n" +
512
		"	void foo(Object o) {\n" +
513
		"	         ^^^^^^\n" +
514
		"Missing nullable annotation: inherited method from Lib declares this parameter as @Nullable\n" +
515
		"----------\n");
516
}
517
// a method relaxes the parameter null specification, super interface declares parameter o as @NonNull
518
// other (first) parameter just repeats the inherited @NonNull
519
public void test_parameter_specification_inheritance_003() {
520
	runConformTest(
521
		new String[] {
522
			"IX.java",
523
			"import org.eclipse.jdt.annotation.*;\n" +
524
			"public interface IX {\n" +
525
			"    void foo(@NonNull String s, @NonNull Object o);\n" +
526
			"}\n",
527
			"X.java",
528
			"import org.eclipse.jdt.annotation.*;\n" +
529
			"public class X implements IX {\n" +
530
			"    public void foo(@NonNull String s, @Nullable Object o) { ; }\n" +
531
			"    void bar() { foo(\"OK\", null); }\n" +
532
			"}\n"
533
		},
534
		"",
535
	    this.LIBS,
536
	    false/*shouldFlush*/,
537
	    null/*vmArgs*/);
538
}
539
// a method adds a @NonNull annotation, super interface has no null annotation
540
// changing other from unconstrained to @Nullable is OK
541
public void test_parameter_specification_inheritance_004() {
542
	runConformTest(
543
		new String[] {
544
			"IX.java",
545
			"public interface IX {\n" +
546
			"    void foo(Object o, Object other);\n" +
547
			"}\n"
548
		});
549
	runNegativeTestWithLibs(
550
		false, // don't flush
551
		new String[] {
552
			"X.java",
553
			"import org.eclipse.jdt.annotation.*;\n" +
554
			"public class X implements IX {\n" +
555
			"    public void foo(@NonNull Object o, @Nullable Object other) { System.out.print(o.toString()); }\n" +
556
			"}\n"
557
		},
558
		null /*customOptions*/,
559
		"----------\n" +
560
		"1. ERROR in X.java (at line 3)\n" +
561
		"	public void foo(@NonNull Object o, @Nullable Object other) { System.out.print(o.toString()); }\n" +
562
		"	                ^^^^^^^^^^^^^^^\n" +
563
		"Illegal redefinition of parameter o, inherited method from IX does not constrain this parameter\n" +
564
		"----------\n");
565
}
566
// a method tries to relax the null contract, super declares @NonNull return
567
public void test_parameter_specification_inheritance_005() {
568
	runConformTestWithLibs(
569
		new String[] {
570
			"Lib.java",
571
			"import org.eclipse.jdt.annotation.*;\n" +
572
			"public class Lib {\n" +
573
			"    @NonNull Object getObject() { return new Object(); }\n" +
574
			"}\n"
575
		},
576
		null /*customOptions*/,
577
		"");
578
	runNegativeTestWithLibs(
579
		false, //dont' flush
580
		new String[] {
581
			"X.java",
582
			"import org.eclipse.jdt.annotation.*;\n" +
583
			"public class X extends Lib {\n" +
584
			"    @Override\n" +
585
			"    @Nullable Object getObject() { return null; }\n" +
586
			"}\n"
587
		},
588
		null /*customOptions*/,
589
		"----------\n" +
590
		"1. ERROR in X.java (at line 4)\n" +
591
		"	@Nullable Object getObject() { return null; }\n" +
592
		"	^^^^^^^^^^^^^^^^\n" +
593
		"The return type is incompatible with the @NonNull return from Lib.getObject()\n" +
594
		"----------\n");
595
}
596
597
// super has no constraint for return, sub method confirms the null contract as @Nullable
598
public void test_parameter_specification_inheritance_006() {
599
	runConformTest(
600
		new String[] {
601
			"Lib.java",
602
			"public class Lib {\n" +
603
			"    Object getObject() { return null; }\n" +
604
			"}\n"
605
		});
606
	runConformTestWithLibs(
607
		false, // don't flush
608
		new String[] {
609
			"X.java",
610
			"import org.eclipse.jdt.annotation.*;\n" +
611
			"public class X extends Lib {\n" +
612
			"    @Override\n" +
613
			"    @Nullable Object getObject() { return null; }\n" +
614
			"}\n"
615
		},
616
		null /*customOptions*/,
617
		"");
618
}
619
// a method body violates the inherited null specification, super declares @NonNull return, missing redeclaration
620
public void test_parameter_specification_inheritance_007() {
621
	runConformTestWithLibs(
622
		new String[] {
623
			"Lib.java",
624
			"import org.eclipse.jdt.annotation.*;\n" +
625
			"public class Lib {\n" +
626
			"    @NonNull Object getObject() { return new Object(); }\n" +
627
			"}\n"
628
		},
629
		null /*customOptions*/,
630
		"");
631
	runNegativeTestWithLibs(
632
		false, // don't flush
633
		new String[] {
634
			"X.java",
635
			"public class X extends Lib {\n" +
636
			"    @Override\n" +
637
			"    Object getObject() { return null; }\n" +
638
			"}\n"
639
		},
640
		null /*customOptions*/,
641
		"----------\n" +
642
		"1. ERROR in X.java (at line 3)\n" +
643
		"	Object getObject() { return null; }\n" +
644
		"	^^^^^^\n" +
645
		"The return type is incompatible with the @NonNull return from Lib.getObject()\n" +
646
		"----------\n");
647
}
648
//a method body violates the @NonNull return specification (repeated from super)
649
public void test_parameter_specification_inheritance_007a() {
650
	runConformTestWithLibs(
651
		new String[] {
652
			"Lib.java",
653
			"import org.eclipse.jdt.annotation.*;\n" +
654
			"public class Lib {\n" +
655
			"    @NonNull Object getObject() { return new Object(); }\n" +
656
			"}\n"
657
		},
658
		null /*customOptions*/,
659
		"");
660
	runNegativeTestWithLibs(
661
		false, // don't flush
662
		new String[] {
663
			"X.java",
664
			"import org.eclipse.jdt.annotation.*;\n" +
665
			"public class X extends Lib {\n" +
666
			"    @Override\n" +
667
			"    @NonNull Object getObject() { return null; }\n" +
668
			"}\n"
669
		},
670
		null /*customOptions*/,
671
		"----------\n" +
672
		"1. ERROR in X.java (at line 4)\n" +
673
		"	@NonNull Object getObject() { return null; }\n" +
674
		"	                                     ^^^^\n" +
675
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
676
		"----------\n");
677
}
678
// a client potentially violates the inherited null specification, super interface declares @NonNull parameter
679
public void test_parameter_specification_inheritance_008() {
680
	Map options = getCompilerOptions();
681
	options.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
682
	runConformTestWithLibs(
683
		new String[] {
684
			"IX.java",
685
			"import org.eclipse.jdt.annotation.*;\n" +
686
			"public interface IX {\n" +
687
			"    void printObject(@NonNull Object o);\n" +
688
			"}\n"
689
		},
690
		null /*customOptions*/,
691
		"");
692
	runNegativeTestWithLibs(
693
		false, // don't flush
694
		new String[] {
695
			"X.java",
696
			"public class X implements IX {\n" +
697
			"    public void printObject(Object o) { System.out.print(o.toString()); }\n" +
698
			"}\n",
699
			"M.java",
700
			"public class M{\n" +
701
			"    void foo(IX x, Object o) {\n" +
702
			"        x.printObject(o);\n" +
703
			"    }\n" +
704
			"}\n"
705
		},
706
		options,
707
		"----------\n" +
708
		// additional error:
709
		"1. ERROR in X.java (at line 2)\n" +
710
		"	public void printObject(Object o) { System.out.print(o.toString()); }\n" +
711
		"	                        ^^^^^^\n" +
712
		"Missing non-null annotation: inherited method from IX declares this parameter as @NonNull\n" +
713
		"----------\n" +
714
		// main error:
715
		"----------\n" +
716
		"1. ERROR in M.java (at line 3)\n" +
717
		"	x.printObject(o);\n" +
718
		"	              ^\n" +
719
		"Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown\n" +
720
		"----------\n");
721
}
722
// a static method has a more relaxed null contract than a like method in the super class, but no overriding.
723
public void test_parameter_specification_inheritance_009() {
724
	runConformTestWithLibs(
725
		new String[] {
726
			"Lib.java",
727
			"import org.eclipse.jdt.annotation.*;\n" +
728
			"public class Lib {\n" +
729
			"    @NonNull static Object getObject() { return new Object(); }\n" +
730
			"}\n",
731
			"X.java",
732
			"import org.eclipse.jdt.annotation.*;\n" +
733
			"public class X extends Lib {\n" +
734
			"    @Nullable static Object getObject() { return null; }\n" +
735
			"}\n"
736
		},
737
		null /*customOptions*/,
738
		"");
739
}
740
// class default is nonnull, method and its super both use the default
741
public void test_parameter_specification_inheritance_010() {
742
	Map customOptions = getCompilerOptions();
743
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
744
	runConformTestWithLibs(
745
		new String[] {
746
	"p1/X.java",
747
			"package p1;\n" +
748
			"import org.eclipse.jdt.annotation.*;\n" +
749
			"@NonNullByDefault\n" +
750
			"public class X {\n" +
751
			"    protected String getString(String s) {\n" +
752
			"        if (Character.isLowerCase(s.charAt(0)))\n" +
753
			"	        return getString(s);\n" +
754
			"	     return s;\n" +
755
			"    }\n" +
756
			"}\n",
757
	"p1/Y.java",
758
			"package p1;\n" +
759
			"import org.eclipse.jdt.annotation.*;\n" +
760
			"@NonNullByDefault\n" +
761
			"public class Y extends X {\n" +
762
			"    @Override\n" +
763
			"    protected String getString(String s) {\n" +
764
			"	     return super.getString(s);\n" +
765
			"    }\n" +
766
			"}\n",
767
		},
768
		customOptions,
769
		"");
770
}
771
// class default is nonnull, method and its super both use the default, super-call passes null
772
public void test_parameter_specification_inheritance_011() {
773
	Map customOptions = getCompilerOptions();
774
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
775
	runNegativeTestWithLibs(
776
		new String[] {
777
	"p1/X.java",
778
			"package p1;\n" +
779
			"import org.eclipse.jdt.annotation.*;\n" +
780
			"@NonNullByDefault\n" +
781
			"public class X {\n" +
782
			"    protected String getString(String s) {\n" +
783
			"        if (Character.isLowerCase(s.charAt(0)))\n" +
784
			"	        return getString(s);\n" +
785
			"	     return s;\n" +
786
			"    }\n" +
787
			"}\n",
788
	"p1/Y.java",
789
			"package p1;\n" +
790
			"import org.eclipse.jdt.annotation.*;\n" +
791
			"@NonNullByDefault\n" +
792
			"public class Y extends X {\n" +
793
			"    @Override\n" +
794
			"    protected String getString(String s) {\n" +
795
			"	     return super.getString(null);\n" +
796
			"    }\n" +
797
			"}\n",
798
		},
799
		customOptions,
800
		"----------\n" +
801
		"1. ERROR in p1\\Y.java (at line 7)\n" +
802
		"	return super.getString(null);\n" +
803
		"	                       ^^^^\n" +
804
		"Type mismatch: required \'@NonNull String\' but the provided value is null\n" +
805
		"----------\n");
806
}
807
// methods from two super types have different null contracts.
808
// sub-class merges both using the weakest common contract
809
public void test_parameter_specification_inheritance_012() {
810
	Map customOptions = getCompilerOptions();
811
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
812
	runConformTestWithLibs(
813
		new String[] {
814
	"p1/X.java",
815
			"package p1;\n" +
816
			"import org.eclipse.jdt.annotation.*;\n" +
817
			"public class X {\n" +
818
			"    public @Nullable String getString(String s1, @Nullable String s2, @NonNull String s3) {\n" +
819
			"	     return s1;\n" +
820
			"    }\n" +
821
			"}\n",
822
	"p1/IY.java",
823
			"package p1;\n" +
824
			"import org.eclipse.jdt.annotation.*;\n" +
825
			"public interface IY {\n" +
826
			"    @NonNull String getString(@NonNull String s1, @NonNull String s2, @Nullable String s3);\n" +
827
			"}\n",
828
	"p1/Y.java",
829
			"package p1;\n" +
830
			"import org.eclipse.jdt.annotation.*;\n" +
831
			"public class Y extends X implements IY {\n" +
832
			"    @Override\n" +
833
			"    public @NonNull String getString(@Nullable String s1, @Nullable String s2, @Nullable String s3) {\n" +
834
			"	     return \"\";\n" +
835
			"    }\n" +
836
			"}\n",
837
		},
838
		customOptions,
839
		"");
840
}
841
// methods from two super types have different null contracts.
842
// sub-class overrides this method in non-conforming ways
843
public void test_parameter_specification_inheritance_013() {
844
	Map customOptions = getCompilerOptions();
845
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
846
	runNegativeTestWithLibs(
847
		new String[] {
848
	"p1/X.java",
849
			"package p1;\n" +
850
			"import org.eclipse.jdt.annotation.*;\n" +
851
			"public class X {\n" +
852
			"    public @Nullable String getString(String s1, @Nullable String s2, @NonNull String s3) {\n" +
853
			"	     return s1;\n" +
854
			"    }\n" +
855
			"}\n",
856
	"p1/IY.java",
857
			"package p1;\n" +
858
			"import org.eclipse.jdt.annotation.*;\n" +
859
			"public interface IY {\n" +
860
			"    @NonNull String getString(@NonNull String s1, @NonNull String s2, @Nullable String s3);\n" +
861
			"}\n",
862
	"p1/Y.java",
863
			"package p1;\n" +
864
			"import org.eclipse.jdt.annotation.*;\n" +
865
			"public class Y extends X implements IY {\n" +
866
			"    @Override\n" +
867
			"    public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
868
			"	     return \"\";\n" +
869
			"    }\n" +
870
			"}\n",
871
		},
872
		customOptions,
873
		"----------\n" +
874
		"1. ERROR in p1\\Y.java (at line 5)\n" +
875
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
876
		"	       ^^^^^^^^^^^^^^^^\n" +
877
		"The return type is incompatible with the @NonNull return from IY.getString(String, String, String)\n" +
878
		"----------\n" +
879
		"2. ERROR in p1\\Y.java (at line 5)\n" +
880
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
881
		"	                                  ^^^^^^\n" +
882
		"Missing non-null annotation: inherited method from IY declares this parameter as @NonNull\n" +
883
		"----------\n" +
884
		"3. ERROR in p1\\Y.java (at line 5)\n" +
885
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
886
		"	                                             ^^^^^^^^^^^^^^^\n" +
887
		"Illegal redefinition of parameter s2, inherited method from X declares this parameter as @Nullable\n" +
888
		"----------\n" +
889
		"4. ERROR in p1\\Y.java (at line 5)\n" +
890
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
891
		"	                                                                 ^^^^^^^^^^^^^^^\n" +
892
		"Illegal redefinition of parameter s3, inherited method from IY declares this parameter as @Nullable\n" +
893
		"----------\n");
894
}
895
// methods from two super types have different null contracts.
896
// sub-class does not override, but should to bridge the incompatibility
897
public void test_parameter_specification_inheritance_014() {
898
	Map customOptions = getCompilerOptions();
899
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
900
	runNegativeTestWithLibs(
901
		new String[] {
902
	"p1/IY.java",
903
			"package p1;\n" +
904
			"import org.eclipse.jdt.annotation.*;\n" +
905
			"public interface IY {\n" +
906
			"    public @NonNull String getString1(String s);\n" +
907
			"    public @NonNull String getString2(String s);\n" +
908
			"    public String getString3(@Nullable String s);\n" +
909
			"    public @NonNull String getString4(@Nullable String s);\n" +
910
			"    public @NonNull String getString5(@Nullable String s);\n" +
911
			"    public @Nullable String getString6(@NonNull String s);\n" +
912
			"}\n",
913
	"p1/X.java",
914
			"package p1;\n" +
915
			"import org.eclipse.jdt.annotation.*;\n" +
916
			"public class X {\n" +
917
			"    public @Nullable String getString1(String s) {\n" + // incomp. return
918
			"	     return s;\n" +
919
			"    }\n" +
920
			"    public String getString2(String s) {\n" +			 // incomp. return
921
			"	     return s;\n" +
922
			"    }\n" +
923
			"    public String getString3(String s) {\n" +			 // incomp. arg
924
			"	     return \"\";\n" +
925
			"    }\n" +
926
			"    public @NonNull String getString4(@Nullable String s) {\n" +
927
			"	     return \"\";\n" +
928
			"    }\n" +
929
			"    public @NonNull String getString5(@NonNull String s) {\n" + // incomp. arg
930
			"	     return s;\n" +
931
			"    }\n" +
932
			"    public @NonNull String getString6(@Nullable String s) {\n" +
933
			"	     return \"\";\n" +
934
			"    }\n" +
935
			"}\n",
936
	"p1/Y.java",
937
			"package p1;\n" +
938
			"public class Y extends X implements IY {\n" +
939
			"}\n",
940
		},
941
		customOptions,
942
		"----------\n" +
943
		"1. ERROR in p1\\Y.java (at line 2)\n" +
944
		"	public class Y extends X implements IY {\n" +
945
		"	             ^\n" +
946
		"The method getString1(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
947
		"----------\n" +
948
		"2. ERROR in p1\\Y.java (at line 2)\n" +
949
		"	public class Y extends X implements IY {\n" +
950
		"	             ^\n" +
951
		"The method getString2(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
952
		"----------\n" +
953
		"3. ERROR in p1\\Y.java (at line 2)\n" +
954
		"	public class Y extends X implements IY {\n" +
955
		"	             ^\n" +
956
		"The method getString5(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
957
		"----------\n" +
958
		"4. ERROR in p1\\Y.java (at line 2)\n" +
959
		"	public class Y extends X implements IY {\n" +
960
		"	             ^\n" +
961
		"The method getString3(String) from X cannot implement the corresponding method from IY due to incompatible nullness constraints\n" +
962
		"----------\n");
963
}
964
// a nullable return value is dereferenced without a check
965
public void test_nullable_return_001() {
966
	runNegativeTestWithLibs(
967
		new String[] {
968
			"X.java",
969
			"import org.eclipse.jdt.annotation.*;\n" +
970
			"public class X {\n" +
971
			"    @Nullable Object getObject() { return null; }\n" +
972
			"    void foo() {\n" +
973
			"        Object o = getObject();\n" +
974
			"        System.out.print(o.toString());\n" +
975
			"    }\n" +
976
			"}\n"
977
		},
978
		"----------\n" +
979
		"1. ERROR in X.java (at line 6)\n" +
980
		"	System.out.print(o.toString());\n" +
981
		"	                 ^\n" +
982
		"Potential null pointer access: The variable o may be null at this location\n" +
983
		"----------\n");
984
}
985
// a nullable return value is dereferenced without a check, method is read from .class file
986
public void test_nullable_return_002() {
987
	runConformTestWithLibs(
988
		new String[] {
989
			"Lib.java",
990
			"import org.eclipse.jdt.annotation.*;\n" +
991
			"public class Lib {\n" +
992
			"    @Nullable Object getObject() { return null; }\n" +
993
			"}\n"
994
		},
995
		null /*customOptions*/,
996
		"");
997
	runNegativeTestWithLibs(
998
		false, // don't flush
999
		new String[] {
1000
			"X.java",
1001
			"public class X {\n" +
1002
			"    void foo(Lib l) {\n" +
1003
			"        Object o = l.getObject();\n" +
1004
			"        System.out.print(o.toString());\n" +
1005
			"    }\n" +
1006
			"}\n"
1007
		},
1008
		null /*customOptions*/,
1009
		"----------\n" +
1010
		"1. ERROR in X.java (at line 4)\n" +
1011
		"	System.out.print(o.toString());\n" +
1012
		"	                 ^\n" +
1013
		"Potential null pointer access: The variable o may be null at this location\n" +
1014
		"----------\n");
1015
}
1016
// a non-null return value is checked for null, method is read from .class file
1017
public void test_nonnull_return_001() {
1018
	runConformTestWithLibs(
1019
		new String[] {
1020
			"Lib.java",
1021
			"import org.eclipse.jdt.annotation.*;\n" +
1022
			"public class Lib {\n" +
1023
			"    @NonNull Object getObject() { return new Object(); }\n" +
1024
			"}\n"
1025
		},
1026
		null /*customOptions*/,
1027
		"");
1028
	runNegativeTestWithLibs(
1029
		false, // don't flush
1030
		new String[] {
1031
			"X.java",
1032
			"public class X {\n" +
1033
			"    void foo(Lib l) {\n" +
1034
			"        Object o = l.getObject();\n" +
1035
			"        if (o != null)\n" +
1036
			"            System.out.print(o.toString());\n" +
1037
			"    }\n" +
1038
			"}\n"
1039
		},
1040
		null /*customOptions*/,
1041
		"----------\n" +
1042
		"1. ERROR in X.java (at line 4)\n" +
1043
		"	if (o != null)\n" +
1044
		"	    ^\n" +
1045
		"Redundant null check: The variable o cannot be null at this location\n" +
1046
		"----------\n");
1047
}
1048
// a non-null method returns null
1049
public void test_nonnull_return_003() {
1050
	runNegativeTestWithLibs(
1051
		new String[] {
1052
			"X.java",
1053
			"import org.eclipse.jdt.annotation.*;\n" +
1054
			"public class X {\n" +
1055
			"    @NonNull Object getObject(boolean b) {\n" +
1056
			"        if (b)\n" +
1057
			"            return null;\n" + // definite specification violation despite enclosing "if"
1058
			"        return new Object();\n" +
1059
			"    }\n" +
1060
			"}\n"
1061
		},
1062
		"----------\n" +
1063
		"1. ERROR in X.java (at line 5)\n" +
1064
		"	return null;\n" +
1065
		"	       ^^^^\n" +
1066
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1067
		"----------\n");
1068
}
1069
// a non-null method potentially returns null
1070
public void test_nonnull_return_004() {
1071
	runNegativeTestWithLibs(
1072
		new String[] {
1073
			"X.java",
1074
			"import org.eclipse.jdt.annotation.*;\n" +
1075
			"public class X {\n" +
1076
			"    @NonNull Object getObject(@Nullable Object o) {\n" +
1077
			"        return o;\n" + // 'o' is only potentially null
1078
			"    }\n" +
1079
			"}\n"
1080
		},
1081
		null /*customOptions*/,
1082
		"----------\n" +
1083
		"1. ERROR in X.java (at line 4)\n" +
1084
		"	return o;\n" +
1085
		"	       ^\n" +
1086
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
1087
		"----------\n");
1088
}
1089
// a non-null method returns its non-null argument
1090
public void test_nonnull_return_005() {
1091
	runConformTestWithLibs(
1092
		new String[] {
1093
			"X.java",
1094
			"import org.eclipse.jdt.annotation.*;\n" +
1095
			"public class X {\n" +
1096
			"    @NonNull Object getObject(@NonNull Object o) {\n" +
1097
			"        return o;\n" +
1098
			"    }\n" +
1099
			"}\n"
1100
		},
1101
		null, // options
1102
		"");
1103
}
1104
//a non-null method has insufficient nullness info for its return value
1105
public void test_nonnull_return_006() {
1106
	runNegativeTestWithLibs(
1107
		new String[] {
1108
			"X.java",
1109
			"import org.eclipse.jdt.annotation.*;\n" +
1110
			"public class X {\n" +
1111
			"    @NonNull Object getObject(Object o) {\n" +
1112
			"        return o;\n" +
1113
			"    }\n" +
1114
			"}\n"
1115
		},
1116
		"----------\n" +
1117
		"1. WARNING in X.java (at line 4)\n" +
1118
		"	return o;\n" +
1119
		"	       ^\n" +
1120
		"Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown\n" +
1121
		"----------\n");
1122
}
1123
// a result from a nullable method is directly dereferenced
1124
public void test_nonnull_return_007() {
1125
	runNegativeTestWithLibs(
1126
		new String[] {
1127
			"X.java",
1128
			"import org.eclipse.jdt.annotation.*;\n" +
1129
			"public class X {\n" +
1130
			"    @Nullable Object getObject() {\n" +
1131
			"        return null;\n" +
1132
			"    }\n" +
1133
			"    void test() {\n" +
1134
			"        getObject().toString();\n" +
1135
			"    }\n" +
1136
			"}\n"
1137
		},
1138
		"----------\n" +
1139
		"1. ERROR in X.java (at line 7)\n" +
1140
		"	getObject().toString();\n" +
1141
		"	^^^^^^^^^^^\n" +
1142
		"Potential null pointer access: The method getObject() may return null\n" +
1143
		"----------\n");
1144
}
1145
// a result from a nonnull method is directly checked for null: redundant
1146
public void test_nonnull_return_008() {
1147
	Map customOptions = getCompilerOptions();
1148
	customOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.ERROR);
1149
	runNegativeTestWithLibs(
1150
		new String[] {
1151
			"X.java",
1152
			"import org.eclipse.jdt.annotation.*;\n" +
1153
			"public class X {\n" +
1154
			"    @NonNull Object getObject() {\n" +
1155
			"        return new Object();\n" +
1156
			"    }\n" +
1157
			"    void test() {\n" +
1158
			"        if (getObject() == null)\n" +
1159
			"		     throw new RuntimeException();\n" +
1160
			"    }\n" +
1161
			"}\n"
1162
		},
1163
		customOptions,
1164
		"----------\n" +
1165
		"1. ERROR in X.java (at line 7)\n" +
1166
		"	if (getObject() == null)\n" +
1167
		"	    ^^^^^^^^^^^\n" +
1168
		"Redundant null check: The method getObject() cannot return null\n" +
1169
		"----------\n");
1170
}
1171
// a result from a nonnull method is directly checked for null (from local): redundant
1172
public void test_nonnull_return_009() {
1173
	Map customOptions = getCompilerOptions();
1174
	customOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.ERROR);
1175
	runNegativeTestWithLibs(
1176
		new String[] {
1177
			"X.java",
1178
			"import org.eclipse.jdt.annotation.*;\n" +
1179
			"public class X {\n" +
1180
			"    @NonNull Object getObject() {\n" +
1181
			"        return new Object();\n" +
1182
			"    }\n" +
1183
			"    void test() {\n" +
1184
			"        Object left = null;\n" +
1185
			"        if (left != getObject())\n" +
1186
			"		     throw new RuntimeException();\n" +
1187
			"    }\n" +
1188
			"}\n"
1189
		},
1190
		customOptions,
1191
		"----------\n" +
1192
		"1. ERROR in X.java (at line 8)\n" +
1193
		"	if (left != getObject())\n" +
1194
		"	    ^^^^\n" +
1195
		"Redundant null check: The variable left can only be null at this location\n" +
1196
		"----------\n" +
1197
		"2. ERROR in X.java (at line 8)\n" +
1198
		"	if (left != getObject())\n" +
1199
		"	            ^^^^^^^^^^^\n" +
1200
		"Redundant null check: The method getObject() cannot return null\n" +
1201
		"----------\n");
1202
}
1203
// a result from a nullable method is assigned and checked for null (from local): not redundant
1204
// see also Bug 336428 - [compiler][null] bogus warning "redundant null check" in condition of do {} while() loop
1205
public void test_nonnull_return_010() {
1206
	Map customOptions = getCompilerOptions();
1207
	customOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.ERROR);
1208
	runNegativeTestWithLibs(
1209
		new String[] {
1210
			"X.java",
1211
			"import org.eclipse.jdt.annotation.*;\n" +
1212
			"public class X {\n" +
1213
			"    @Nullable X getX() {\n" +
1214
			"        return new X();\n" +
1215
			"    }\n" +
1216
			"    void test() {\n" +
1217
			"        X left = this;\n" +
1218
			"        do {\n" +
1219
			"            if (left == null) \n" +
1220
			"	   	         throw new RuntimeException();\n" +
1221
			"        } while ((left = left.getX()) != null);\n" + // no warning/error here!
1222
			"    }\n" +
1223
			"}\n"
1224
		},
1225
		customOptions,
1226
		"----------\n" +
1227
		"1. ERROR in X.java (at line 9)\n" +
1228
		"	if (left == null) \n" +
1229
		"	    ^^^^\n" +
1230
		"Null comparison always yields false: The variable left cannot be null at this location\n" +
1231
		"----------\n");
1232
}
1233
// a non-null method returns a checked-for null value, but that branch is dead code
1234
public void test_nonnull_return_011() {
1235
	Map customOptions = getCompilerOptions();
1236
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1237
	runNegativeTestWithLibs(
1238
		new String[] {
1239
			"X.java",
1240
			"import org.eclipse.jdt.annotation.*;\n" +
1241
			"@NonNullByDefault\n" +
1242
			"public class X {\n" +
1243
			"    Object getObject(Object dubious) {\n" +
1244
			"        if (dubious == null)\n" + // redundant
1245
			"            return dubious;\n" + // definitely null, but not reported inside dead code
1246
			"        return new Object();\n" +
1247
			"    }\n" +
1248
			"}\n"
1249
		},
1250
		customOptions,
1251
		"----------\n" +
1252
		"1. ERROR in X.java (at line 5)\n" +
1253
		"	if (dubious == null)\n" +
1254
		"	    ^^^^^^^\n" +
1255
		"Null comparison always yields false: The variable dubious cannot be null at this location\n" +
1256
		"----------\n" +
1257
		"2. WARNING in X.java (at line 6)\n" +
1258
		"	return dubious;\n" +
1259
		"	^^^^^^^^^^^^^^^\n" +
1260
		"Dead code\n" +
1261
		"----------\n");
1262
}
1263
// a non-null method returns a definite null from a conditional expression
1264
// requires the fix for Bug 354554 - [null] conditional with redundant condition yields weak error message
1265
// TODO(SH): ENABLE!
1266
public void _test_nonnull_return_012() {
1267
	Map customOptions = getCompilerOptions();
1268
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1269
	runNegativeTestWithLibs(
1270
		new String[] {
1271
			"X.java",
1272
			"import org.eclipse.jdt.annotation.*;\n" +
1273
			"@NonNullByDefault\n" +
1274
			"public class X {\n" +
1275
			"    Object getObject(Object dubious) {\n" +
1276
			"        return dubious == null ? dubious : null;\n" +
1277
			"    }\n" +
1278
			"}\n"
1279
		},
1280
		customOptions,
1281
		"----------\n" +
1282
		"1. ERROR in X.java (at line 5)\n" +
1283
		"	return dubious == null ? dubious : null;\n" +
1284
		"	       ^^^^^^^\n" +
1285
		"Null comparison always yields false: The variable dubious cannot be null at this location\n" +
1286
		"----------\n" +
1287
		"2. ERROR in X.java (at line 5)\n" +
1288
		"	return dubious == null ? dubious : null;\n" +
1289
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
1290
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1291
		"----------\n");
1292
}
1293
// don't apply any default annotations to return void
1294
public void test_nonnull_return_013() {
1295
	Map customOptions = getCompilerOptions();
1296
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1297
	runConformTestWithLibs(
1298
		new String[] {
1299
			"X.java",
1300
			"import org.eclipse.jdt.annotation.*;\n" +
1301
			"@NonNullByDefault\n" +
1302
			"public class X {\n" +
1303
			"    void getObject() {}\n" +
1304
			"}\n",
1305
			"Y.java",
1306
			"public class Y extends X {\n" +
1307
			"    @Override\n" +
1308
			"    void getObject() {}\n" + // don't complain, void takes no (default) annotation
1309
			"}\n"
1310
		},
1311
		customOptions,
1312
		"");
1313
}
1314
//suppress an error regarding null-spec violation
1315
public void test_suppress_001() {
1316
	Map customOptions = getCompilerOptions();
1317
	customOptions.put(JavaCore.COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS, JavaCore.ENABLED);
1318
	runConformTestWithLibs(
1319
			new String[] {
1320
				"X.java",
1321
				"import org.eclipse.jdt.annotation.*;\n" +
1322
				"public class X {\n" +
1323
				"    @SuppressWarnings(\"null\")\n" +
1324
				"    @NonNull Object getObject(@Nullable Object o) {\n" +
1325
				"        return o;\n" + // 'o' is only potentially null
1326
				"    }\n" +
1327
				"}\n"
1328
			},
1329
			customOptions,
1330
			"");
1331
}
1332
// mixed use of fully qualified name / explicit import
1333
public void test_annotation_import_001() {
1334
	Map customOptions = getCompilerOptions();
1335
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "org.foo.Nullable");
1336
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1337
	runConformTestWithLibs(
1338
		new String[] {
1339
			CUSTOM_NULLABLE_NAME,
1340
			CUSTOM_NULLABLE_CONTENT,
1341
			CUSTOM_NONNULL_NAME,
1342
			CUSTOM_NONNULL_CONTENT,
1343
			"Lib.java",
1344
			"public class Lib {\n" +
1345
			"    @org.foo.NonNull Object getObject() { return new Object(); }\n" + 	// FQN
1346
			"}\n",
1347
			"X.java",
1348
			"import org.foo.NonNull;\n" +											// explicit import
1349
			"public class X {\n" +
1350
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
1351
			"        return l.getObject();\n" +
1352
			"    }\n" +
1353
			"}\n"
1354
		},
1355
		customOptions,
1356
		"");
1357
}
1358
1359
// use of explicit imports throughout
1360
public void test_annotation_import_002() {
1361
	Map customOptions = getCompilerOptions();
1362
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "org.foo.Nullable");
1363
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1364
	runConformTest(
1365
		new String[] {
1366
			CUSTOM_NULLABLE_NAME,
1367
			CUSTOM_NULLABLE_CONTENT,
1368
			CUSTOM_NONNULL_NAME,
1369
			CUSTOM_NONNULL_CONTENT,
1370
			"Lib.java",
1371
			"import org.foo.NonNull;\n" +
1372
			"public class Lib {\n" +
1373
			"    @NonNull Object getObject() { return new Object(); }\n" +
1374
			"}\n",
1375
			"X.java",
1376
			"import org.foo.NonNull;\n" +
1377
			"public class X {\n" +
1378
			"    @NonNull Object getObject(@org.foo.Nullable String dummy, @NonNull Lib l) {\n" +
1379
			"        Object o = l.getObject();" +
1380
			"        return o;\n" +
1381
			"    }\n" +
1382
			"}\n"
1383
		},
1384
		customOptions,
1385
		"");
1386
}
1387
// explicit import of existing annotation types
1388
// using a Lib without null specifications
1389
public void test_annotation_import_005() {
1390
	Map customOptions = getCompilerOptions();
1391
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1392
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "org.foo.MayBeNull");
1393
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.MustNotBeNull");
1394
	runNegativeTest(
1395
		true/*shouldFlushOutputDirectory*/,
1396
		new String[] {
1397
			"org/foo/MayBeNull.java",
1398
			"package org.foo;\n" +
1399
			"import java.lang.annotation.*;\n" +
1400
			"@Retention(RetentionPolicy.CLASS)\n" +
1401
			"public @interface MayBeNull {}\n",
1402
1403
			"org/foo/MustNotBeNull.java",
1404
			"package org.foo;\n" +
1405
			"import java.lang.annotation.*;\n" +
1406
			"@Retention(RetentionPolicy.CLASS)\n" +
1407
			"public @interface MustNotBeNull {}\n",
1408
1409
			"Lib.java",
1410
			"public class Lib {\n" +
1411
			"    Object getObject() { return new Object(); }\n" +
1412
			"}\n",
1413
			"X.java",
1414
			"import org.foo.*;\n" +
1415
			"public class X {\n" +
1416
			"    @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1417
			"        return l.getObject();\n" +
1418
			"    }\n" +
1419
			"}\n",
1420
1421
		},
1422
		null /*no libs*/,
1423
		customOptions,
1424
		"----------\n" +
1425
		"1. ERROR in X.java (at line 4)\n" +
1426
		"	return l.getObject();\n" +
1427
		"	       ^^^^^^^^^^^^^\n" +
1428
		"Potential type mismatch: required \'@MustNotBeNull Object\' but nullness of the provided value is unknown\n" +
1429
		"----------\n",
1430
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1431
}
1432
// a non-null method returns a value obtained from an unannotated method, missing annotation types
1433
public void test_annotation_import_006() {
1434
	Map customOptions = getCompilerOptions();
1435
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1436
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "org.foo.MayBeNull");
1437
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.MustNotBeNull");
1438
	runNegativeTest(
1439
		true/*shouldFlushOutputDirectory*/,
1440
		new String[] {
1441
			"Lib.java",
1442
			"public class Lib {\n" +
1443
			"    Object getObject() { return new Object(); }\n" +
1444
			"}\n",
1445
			"X.java",
1446
			"public class X {\n" +
1447
			"    @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1448
			"        return l.getObject();\n" +
1449
			"    }\n" +
1450
			"}\n"
1451
		},
1452
		null /* no libs */,
1453
		customOptions,
1454
		"----------\n" +
1455
		"1. ERROR in X.java (at line 2)\n" +
1456
		"	@MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1457
		"	 ^^^^^^^^^^^^^\n" +
1458
		"MustNotBeNull cannot be resolved to a type\n" +
1459
		"----------\n" +
1460
		"2. ERROR in X.java (at line 2)\n" +
1461
		"	@MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1462
		"	                                 ^^^^^^^^^^^^^\n" +
1463
		"MustNotBeNull cannot be resolved to a type\n" +
1464
		"----------\n",
1465
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1466
}
1467
// using nullness defaulting to nonnull, missing annotation types
1468
public void test_annotation_import_007() {
1469
	Map customOptions = getCompilerOptions();
1470
	customOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO, JavaCore.ERROR);
1471
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "org.foo.MayBeNull");
1472
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.MustNotBeNull");
1473
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1474
	runNegativeTest(
1475
		true/*shouldFlushOutputDirectory*/,
1476
		new String[] {
1477
			"Lib.java",
1478
			"public class Lib {\n" +
1479
			"    Object getObject() { return new Object(); }\n" +
1480
			"}\n",
1481
			"X.java",
1482
			"public class X {\n" +
1483
			"    Object getObject(Lib l) {\n" +
1484
			"        return l.getObject();\n" +
1485
			"    }\n" +
1486
			"}\n"
1487
		},
1488
		this.LIBS,
1489
		customOptions,
1490
		"----------\n" +
1491
		"1. ERROR in Lib.java (at line 1)\n" +
1492
		"	public class Lib {\n" +
1493
		"	^\n" +
1494
		"Buildpath problem: the type org.foo.MustNotBeNull, which is configured as a null annotation type, cannot be resolved\n" +
1495
		"----------\n",
1496
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1497
}
1498
1499
// a null annotation is illegally used on a class:
1500
public void test_illegal_annotation_001() {
1501
	runNegativeTest(
1502
		new String[] {
1503
			"X.java",
1504
			"import org.eclipse.jdt.annotation.*;\n" +
1505
			"@NonNull public class X {\n" +
1506
			"}\n"
1507
		},
1508
		"----------\n" +
1509
		"1. ERROR in X.java (at line 2)\n" +
1510
		"	@NonNull public class X {\n" +
1511
		"	^^^^^^^^\n" +
1512
		"The annotation @NonNull is disallowed for this location\n" +
1513
		"----------\n",
1514
		this.LIBS,
1515
		false/*shouldFlush*/);
1516
}
1517
// this test has been removed:
1518
// setting default to nullable, default applies to a parameter
1519
// public void test_default_nullness_001()
1520
1521
// a null annotation is illegally defined by its simple name
1522
// disabled because specific error is not currently raised
1523
public void _test_illegal_annotation_002() {
1524
	Map customOptions = getCompilerOptions();
1525
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "NichtNull");
1526
	runNegativeTestWithLibs(
1527
		new String[] {
1528
			"X.java",
1529
			"public class X {\n" +
1530
			"}\n"
1531
		},
1532
		customOptions,
1533
		"----------\n" +
1534
		"1. ERROR in X.java (at line 1)\n" +
1535
		"	public class X {\n" +
1536
		"	^\n" +
1537
		"Cannot use the unqualified name \'NichtNull\' as an annotation name for null specification\n" +
1538
		"----------\n");
1539
}
1540
1541
// a null annotation is illegally used on a void method:
1542
public void test_illegal_annotation_003() {
1543
	runNegativeTest(
1544
		new String[] {
1545
			"X.java",
1546
			"import org.eclipse.jdt.annotation.*;\n" +
1547
			"public class X {\n" +
1548
			"	@NonNull void foo() {}\n" +
1549
			"}\n"
1550
		},
1551
		"----------\n" +
1552
		"1. ERROR in X.java (at line 3)\n" +
1553
		"	@NonNull void foo() {}\n" +
1554
		"	^^^^^^^^^^^^^\n" +
1555
		"The nullness annotation @NonNull is not applicable for the primitive type void\n" +
1556
		"----------\n",
1557
		this.LIBS,
1558
		false/*shouldFlush*/);
1559
}
1560
1561
// a null annotation is illegally used on a primitive type parameter
1562
public void test_illegal_annotation_004() {
1563
	runNegativeTest(
1564
		new String[] {
1565
			"X.java",
1566
			"import org.eclipse.jdt.annotation.*;\n" +
1567
			"public class X {\n" +
1568
			"	void foo(@Nullable int i) {}\n" +
1569
			"}\n"
1570
		},
1571
		"----------\n" +
1572
		"1. ERROR in X.java (at line 3)\n" +
1573
		"	void foo(@Nullable int i) {}\n" +
1574
		"	         ^^^^^^^^^^^^^\n" +
1575
		"The nullness annotation @Nullable is not applicable for the primitive type int\n" +
1576
		"----------\n",
1577
		this.LIBS,
1578
		false/*shouldFlush*/);
1579
}
1580
1581
// a null annotation is illegally used on a primitive type local var
1582
public void test_illegal_annotation_005() {
1583
	runNegativeTest(
1584
		new String[] {
1585
			"X.java",
1586
			"import org.eclipse.jdt.annotation.*;\n" +
1587
			"public class X {\n" +
1588
			"	int foo() {\n" +
1589
			"       @Nullable int i = 3;\n" +
1590
			"       return i;\n" +
1591
			"   }\n" +
1592
			"}\n"
1593
		},
1594
		"----------\n" +
1595
		"1. ERROR in X.java (at line 4)\n" +
1596
		"	@Nullable int i = 3;\n" +
1597
		"	^^^^^^^^^^^^^\n" +
1598
		"The nullness annotation @Nullable is not applicable for the primitive type int\n" +
1599
		"----------\n",
1600
		this.LIBS,
1601
		false/*shouldFlush*/);
1602
}
1603
1604
// a configured annotation type does not exist
1605
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342#c133
1606
public void test_illegal_annotation_006() {
1607
	Map customOptions = getCompilerOptions();
1608
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "nullAnn.Nullable");
1609
	runNegativeTestWithLibs(
1610
		new String[] {
1611
			"p/Test.java",
1612
			"package p;\n" +
1613
			"import nullAnn.*;  // 1 \n" +
1614
			"\n" +
1615
			"public class Test { \n" +
1616
			"\n" +
1617
			"        void foo(@nullAnn.Nullable  Object o) {   // 2\n" +
1618
			"            o.toString();           \n" +
1619
			"        }\n" +
1620
			"}"
1621
		},
1622
		customOptions,
1623
		"----------\n" +
1624
		"1. ERROR in p\\Test.java (at line 2)\n" +
1625
		"	import nullAnn.*;  // 1 \n" +
1626
		"	       ^^^^^^^\n" +
1627
		"The import nullAnn cannot be resolved\n" +
1628
		"----------\n" +
1629
		"2. ERROR in p\\Test.java (at line 6)\n" +
1630
		"	void foo(@nullAnn.Nullable  Object o) {   // 2\n" +
1631
		"	          ^^^^^^^\n" +
1632
		"nullAnn cannot be resolved to a type\n" +
1633
		"----------\n");
1634
}
1635
1636
public void test_default_nullness_002() {
1637
	Map customOptions = getCompilerOptions();
1638
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1639
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1640
	runNegativeTestWithLibs(
1641
		new String[] {
1642
			"X.java",
1643
			"import org.eclipse.jdt.annotation.*;\n" +
1644
			"public class X {\n" +
1645
			"    Object getObject(@Nullable Object o) {\n" +
1646
			"        return new Object();\n" +
1647
			"    }\n" +
1648
			"}\n",
1649
			"Y.java",
1650
			"import org.eclipse.jdt.annotation.*;\n" +
1651
			"public class Y extends X {\n" +
1652
			"    @Override\n" +
1653
			"    @Nullable Object getObject(Object o) {\n" + // complain illegal return redef and inherited annot is not repeated
1654
			"        return o;\n" +
1655
			"    }\n" +
1656
			"}\n",
1657
		},
1658
		customOptions,
1659
		// main error:
1660
		"----------\n" +
1661
		"1. ERROR in Y.java (at line 4)\n" +
1662
		"	@Nullable Object getObject(Object o) {\n" +
1663
		"	^^^^^^^^^^^^^^^^\n" +
1664
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" +
1665
		"----------\n" +
1666
		// additional error:
1667
		"2. ERROR in Y.java (at line 4)\n" +
1668
		"	@Nullable Object getObject(Object o) {\n" +
1669
		"	                           ^^^^^^\n" +
1670
		"Illegal redefinition of parameter o, inherited method from X declares this parameter as @Nullable\n" +
1671
		"----------\n");
1672
}
1673
// package default is non-null
1674
public void test_default_nullness_003() {
1675
	Map customOptions = getCompilerOptions();
1676
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1677
	runNegativeTestWithLibs(
1678
		new String[] {
1679
	"p1/X.java",
1680
			"package p1;\n" +
1681
			"import org.eclipse.jdt.annotation.*;\n" +
1682
			"@NonNullByDefault\n" +
1683
			"public class X {\n" +
1684
			"    protected Object getObject(@Nullable Object o) {\n" +
1685
			"        return new Object();\n" +
1686
			"    }\n" +
1687
			"}\n",
1688
	"p2/package-info.java",
1689
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1690
			"package p2;\n",
1691
	"p2/Y.java",
1692
			"package p2;\n" +
1693
			"import org.eclipse.jdt.annotation.*;\n" +
1694
			"public class Y extends p1.X {\n" +
1695
			"    @Override\n" +
1696
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" +
1697
			"        bar(o);\n" +
1698
			"        return o;\n" +
1699
			"    }\n" +
1700
			"	 void bar(Object o2) { }\n" + // parameter is nonnull per package default
1701
			"}\n"
1702
		},
1703
		customOptions,
1704
		"----------\n" +
1705
		"1. ERROR in p2\\Y.java (at line 5)\n" +
1706
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" +
1707
		"	          ^^^^^^^^^^^^^^^^\n" +
1708
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" +
1709
		"----------\n" +
1710
		"2. ERROR in p2\\Y.java (at line 6)\n" +
1711
		"	bar(o);\n" +
1712
		"	    ^\n" +
1713
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
1714
		"----------\n");
1715
}
1716
// package level default is consumed from package-info.class
1717
public void test_default_nullness_003a() {
1718
	Map customOptions = getCompilerOptions();
1719
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1720
	runConformTestWithLibs(
1721
		new String[] {
1722
	"p1/X.java",
1723
			"package p1;\n" +
1724
			"import org.eclipse.jdt.annotation.*;\n" +
1725
			"@NonNullByDefault\n" +
1726
			"public class X {\n" +
1727
			"    protected Object getObject(@Nullable Object o) {\n" +
1728
			"        return new Object();\n" +
1729
			"    }\n" +
1730
			"	 protected void bar(Object o2) { }\n" + // parameter is nonnull per type default
1731
			"}\n",
1732
	"p2/package-info.java",
1733
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1734
			"package p2;\n",
1735
			},
1736
			customOptions,
1737
			"");
1738
	// check if default is visible from package-info.class.
1739
	runNegativeTestWithLibs(
1740
		false, // don't flush
1741
		new String[] {
1742
	"p2/Y.java",
1743
			"package p2;\n" +
1744
			"import org.eclipse.jdt.annotation.*;\n" +
1745
			"public class Y extends p1.X {\n" +
1746
			"    @Override\n" +
1747
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" + // can't override inherited default nonnull
1748
			"        bar(o);\n" + // parameter is nonnull in super class's .class file
1749
			"        accept(o);\n" +
1750
			"        return o;\n" +
1751
			"    }\n" +
1752
			"    void accept(Object a) {}\n" + // governed by package level default
1753
			"}\n"
1754
		},
1755
		customOptions,
1756
		"----------\n" +
1757
		"1. ERROR in p2\\Y.java (at line 5)\n" +
1758
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" +
1759
		"	          ^^^^^^^^^^^^^^^^\n" +
1760
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" +
1761
		"----------\n" +
1762
		"2. ERROR in p2\\Y.java (at line 6)\n" +
1763
		"	bar(o);\n" +
1764
		"	    ^\n" +
1765
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
1766
		"----------\n" +
1767
		"3. ERROR in p2\\Y.java (at line 7)\n" +
1768
		"	accept(o);\n" +
1769
		"	       ^\n" +
1770
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
1771
		"----------\n");
1772
}
1773
// don't apply type-level default to non-reference type
1774
public void test_default_nullness_004() {
1775
	Map customOptions = getCompilerOptions();
1776
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1777
	runConformTestWithLibs(
1778
		new String[] {
1779
	"p1/X.java",
1780
			"package p1;\n" +
1781
			"import org.eclipse.jdt.annotation.*;\n" +
1782
			"@NonNullByDefault\n" +
1783
			"public class X {\n" +
1784
			"    protected Object getObject(boolean o) {\n" +
1785
			"        return new Object();\n" +
1786
			"    }\n" +
1787
			"}\n",
1788
	"p2/Y.java",
1789
			"package p2;\n" +
1790
			"import org.eclipse.jdt.annotation.*;\n" +
1791
			"public class Y extends p1.X {\n" +
1792
			"    @Override\n" +
1793
			"    protected @NonNull Object getObject(boolean o) {\n" +
1794
			"        return o ? this : new Object();\n" +
1795
			"    }\n" +
1796
			"}\n"
1797
		},
1798
		customOptions,
1799
		"");
1800
}
1801
// package default is non-null
1802
// see also Bug 354536 - compiling package-info.java still depends on the order of compilation units
1803
public void test_default_nullness_005() {
1804
	Map customOptions = getCompilerOptions();
1805
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1806
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1807
	runNegativeTestWithLibs(
1808
		new String[] {
1809
	"p1/X.java",
1810
			"package p1;\n" +
1811
			"public class X {\n" +
1812
			"    class Inner {" +
1813
			"        protected Object getObject(String s) {\n" +
1814
			"            return null;\n" +
1815
			"        }\n" +
1816
			"    }\n" +
1817
			"}\n",
1818
	"p1/package-info.java",
1819
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1820
			"package p1;\n",
1821
	CUSTOM_NONNULL_NAME,
1822
			CUSTOM_NONNULL_CONTENT
1823
		},
1824
		customOptions,
1825
		"----------\n" +
1826
		"1. ERROR in p1\\X.java (at line 4)\n" +
1827
		"	return null;\n" +
1828
		"	       ^^^^\n" +
1829
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1830
		"----------\n");
1831
}
1832
// package default is non-null, package-info.java read before the annotation type
1833
// compile order: beginToCompile(X.Inner) triggers reading of package-info.java before the annotation type was read
1834
public void test_default_nullness_006() {
1835
	Map customOptions = getCompilerOptions();
1836
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1837
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1838
	runNegativeTestWithLibs(
1839
		new String[] {
1840
	"p1/package-info.java",
1841
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1842
			"package p1;\n",
1843
	"p1/X.java",
1844
			"package p1;\n" +
1845
			"public class X {\n" +
1846
			"    class Inner {" +
1847
			"        protected Object getObject(String s) {\n" +
1848
			"            return null;\n" +
1849
			"        }\n" +
1850
			"    }\n" +
1851
			"}\n",
1852
	CUSTOM_NONNULL_NAME,
1853
			CUSTOM_NONNULL_CONTENT
1854
		},
1855
		customOptions,
1856
		"----------\n" +
1857
		"1. ERROR in p1\\X.java (at line 4)\n" +
1858
		"	return null;\n" +
1859
		"	       ^^^^\n" +
1860
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1861
		"----------\n");
1862
}
1863
// global default nonnull, but return may be null
1864
public void test_default_nullness_007() {
1865
	Map customOptions = getCompilerOptions();
1866
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1867
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1868
	runNegativeTestWithLibs(
1869
		new String[] {
1870
			"X.java",
1871
			"import org.eclipse.jdt.annotation.*;\n" +
1872
			"public class X {\n" +
1873
			"    @Nullable Object dangerous() {\n" +
1874
			"        return null;\n" +
1875
			"    }\n" +
1876
			"    Object broken() {\n" +
1877
			"        return dangerous();\n" +
1878
			"    }\n" +
1879
			"}\n",
1880
1881
		},
1882
		customOptions,
1883
		"----------\n" +
1884
		"1. ERROR in X.java (at line 7)\n" +
1885
		"	return dangerous();\n" +
1886
		"	       ^^^^^^^^^^^\n" +
1887
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" +
1888
		"----------\n");
1889
}
1890
1891
// cancel type level default to comply with super specification
1892
public void test_default_nullness_008() {
1893
	Map customOptions = getCompilerOptions();
1894
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1895
	runConformTestWithLibs(
1896
		new String[] {
1897
	"p1/X.java",
1898
			"package p1;\n" +
1899
			"public class X {\n" +
1900
			"    protected Object getObject(Object o) {\n" +
1901
			"        return new Object();\n" +
1902
			"    }\n" +
1903
			"}\n",
1904
	"p2/Y.java",
1905
			"package p2;\n" +
1906
			"import org.eclipse.jdt.annotation.*;\n" +
1907
			"@NonNullByDefault\n" +
1908
			"public class Y extends p1.X {\n" +
1909
			"    @Override\n" +
1910
			"    @NonNullByDefault(false)\n" +
1911
			"    protected Object getObject(Object o) {\n" +
1912
			"        if (o.toString().length() == 0)\n" + // dereference without a warning
1913
			"	        return null;\n" + // return null without a warning
1914
			"        return o.toString();\n" +
1915
			"    }\n" +
1916
			"}\n"
1917
		},
1918
		customOptions,
1919
		"");
1920
}
1921
1922
// cancel outer type level default to comply with super specification
1923
public void test_default_nullness_009() {
1924
	Map customOptions = getCompilerOptions();
1925
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1926
	runNegativeTestWithLibs(
1927
		new String[] {
1928
	"p1/X.java",
1929
			"package p1;\n" +
1930
			"public class X {\n" +
1931
			"    protected Object getObject(Object o) {\n" +
1932
			"        return new Object();\n" +
1933
			"    }\n" +
1934
			"}\n",
1935
	"p2/Y.java",
1936
			"package p2;\n" +
1937
			"import org.eclipse.jdt.annotation.*;\n" +
1938
			"@NonNullByDefault\n" +
1939
			"public class Y { \n" +
1940
			"    @NonNullByDefault(false)\n" +
1941
			"    static class Z extends p1.X {\n" +
1942
			"        @Override\n" +
1943
			"        protected Object getObject(Object o) {\n" +
1944
			"            if (o.toString().length() == 0) {\n" +
1945
			"                o = null;\n" + // assign null without a warning
1946
			"                bar(o); // error: arg is declared @NonNull\n" +
1947
			"	             return null;\n" +
1948
			"            }\n" +
1949
			"            return o.toString();\n" +
1950
			"        }\n" +
1951
			"        String bar(@NonNull Object o) {\n" +
1952
			"            return getObject(o).toString();" +
1953
			"        }\n" +
1954
			"    }\n" +
1955
			"}\n"
1956
		},
1957
		customOptions,
1958
		"----------\n" +
1959
		"1. ERROR in p2\\Y.java (at line 11)\n" +
1960
		"	bar(o); // error: arg is declared @NonNull\n" +
1961
		"	    ^\n" +
1962
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1963
		"----------\n");
1964
}
1965
// non-null declarations are redundant within a default scope.
1966
public void test_default_nullness_010() {
1967
	Map customOptions = getCompilerOptions();
1968
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1969
	runConformTestWithLibs(
1970
		new String[] {
1971
	"p2/Y.java",
1972
			"package p2;\n" +
1973
			"import org.eclipse.jdt.annotation.*;\n" +
1974
			"@NonNullByDefault\n" +
1975
			"public class Y {\n" +
1976
			"    protected @NonNull Object getObject(@NonNull Object o) {\n" +
1977
			"        return o;\n" +
1978
			"    }\n" +
1979
			"}\n"
1980
		},
1981
		customOptions,
1982
		"----------\n" +
1983
		"1. WARNING in p2\\Y.java (at line 5)\n" +
1984
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" +
1985
		"	          ^^^^^^^^^^^^^^^\n" +
1986
		"The nullness annotation is redundant with a default that applies to this location\n" +
1987
		"----------\n" +
1988
		"2. WARNING in p2\\Y.java (at line 5)\n" +
1989
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" +
1990
		"	                                    ^^^^^^^^^^^^^^^^^\n" +
1991
		"The nullness annotation is redundant with a default that applies to this location\n" +
1992
		"----------\n");
1993
}
1994
// a nonnull variable is dereferenced in a loop
1995
public void test_nonnull_var_in_constrol_structure_1() {
1996
	Map customOptions = getCompilerOptions();
1997
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1998
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1999
	runNegativeTestWithLibs(
2000
		new String[] {
2001
			"X.java",
2002
			"import org.eclipse.jdt.annotation.*;\n" +
2003
			"public class X {\n" +
2004
			"    void print4(@NonNull String s) {\n" +
2005
			"        for (int i=0; i<4; i++)\n" +
2006
			"             print(s);\n" +
2007
			"    }\n" +
2008
			"    void print5(@Nullable String s) {\n" +
2009
			"        for (int i=0; i<5; i++)\n" +
2010
			"             print(s);\n" +
2011
			"    }\n" +
2012
			"    void print6(boolean b) {\n" +
2013
			"        String s = b ? null : \"\";\n" +
2014
			"        for (int i=0; i<5; i++)\n" +
2015
			"             print(s);\n" +
2016
			"    }\n" +
2017
			"    void print(@NonNull String s) {\n" +
2018
			"        System.out.print(s);\n" +
2019
			"    }\n" +
2020
			"}\n",
2021
2022
		},
2023
		customOptions,
2024
		"----------\n" +
2025
		"1. WARNING in X.java (at line 3)\n" +
2026
		"	void print4(@NonNull String s) {\n" +
2027
		"	            ^^^^^^^^^^^^^^^^^\n" +
2028
		"The nullness annotation is redundant with a default that applies to this location\n" +
2029
		"----------\n" +
2030
		"2. ERROR in X.java (at line 9)\n" +
2031
		"	print(s);\n" +
2032
		"	      ^\n" +
2033
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2034
		"----------\n" +
2035
		"3. ERROR in X.java (at line 14)\n" +
2036
		"	print(s);\n" +
2037
		"	      ^\n" +
2038
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2039
		"----------\n" +
2040
		"4. WARNING in X.java (at line 16)\n" +
2041
		"	void print(@NonNull String s) {\n" +
2042
		"	           ^^^^^^^^^^^^^^^^^\n" +
2043
		"The nullness annotation is redundant with a default that applies to this location\n" +
2044
		"----------\n");
2045
}
2046
// a nonnull variable is dereferenced in a finally block
2047
public void test_nonnull_var_in_constrol_structure_2() {
2048
	Map customOptions = getCompilerOptions();
2049
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2050
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2051
	runNegativeTestWithLibs(
2052
		new String[] {
2053
			"X.java",
2054
			"import org.eclipse.jdt.annotation.*;\n" +
2055
			"public class X {\n" +
2056
			"    void print4(String s) {\n" +
2057
			"        try { /*empty*/ } finally {\n" +
2058
			"             print(s);\n" +
2059
			"        }\n" +
2060
			"    }\n" +
2061
			"    void print5(@Nullable String s) {\n" +
2062
			"        try { /*empty*/ } finally {\n" +
2063
			"             print(s);\n" +
2064
			"        }\n" +
2065
			"    }\n" +
2066
			"    void print6(boolean b) {\n" +
2067
			"        String s = b ? null : \"\";\n" +
2068
			"        try { /*empty*/ } finally {\n" +
2069
			"             print(s);\n" +
2070
			"        }\n" +
2071
			"    }\n" +
2072
			"    void print(String s) {\n" +
2073
			"        System.out.print(s);\n" +
2074
			"    }\n" +
2075
			"}\n",
2076
2077
		},
2078
		customOptions,
2079
		"----------\n" +
2080
		"1. ERROR in X.java (at line 10)\n" +
2081
		"	print(s);\n" +
2082
		"	      ^\n" +
2083
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2084
		"----------\n" +
2085
		"2. ERROR in X.java (at line 16)\n" +
2086
		"	print(s);\n" +
2087
		"	      ^\n" +
2088
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2089
		"----------\n");
2090
}
2091
// a nonnull variable is dereferenced in a finally block inside a loop
2092
public void test_nonnull_var_in_constrol_structure_3() {
2093
	Map customOptions = getCompilerOptions();
2094
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2095
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2096
	customOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.IGNORE);
2097
	runNegativeTestWithLibs(
2098
		new String[] {
2099
			"X.java",
2100
			"import org.eclipse.jdt.annotation.*;\n" +
2101
			"public class X {\n" +
2102
			"    void print4(@NonNull String s) {\n" +
2103
			"        for (int i=0; i<4; i++)\n" +
2104
			"            try { /*empty*/ } finally {\n" +
2105
			"                 print(s);\n" +
2106
			"            }\n" +
2107
			"    }\n" +
2108
			"    void print5(@Nullable String s) {\n" +
2109
			"        for (int i=0; i<5; i++)\n" +
2110
			"            try { /*empty*/ } finally {\n" +
2111
			"                 print(s);\n" +
2112
			"            }\n" +
2113
			"    }\n" +
2114
			"    void print6(boolean b) {\n" +
2115
			"        String s = b ? null : \"\";\n" +
2116
			"        for (int i=0; i<4; i++)\n" +
2117
			"            try { /*empty*/ } finally {\n" +
2118
			"                 print(s);\n" +
2119
			"            }\n" +
2120
			"    }\n" +
2121
			"    void print(@NonNull String s) {\n" +
2122
			"        System.out.print(s);\n" +
2123
			"    }\n" +
2124
			"}\n",
2125
2126
		},
2127
		customOptions,
2128
		"----------\n" +
2129
		"1. ERROR in X.java (at line 12)\n" +
2130
		"	print(s);\n" +
2131
		"	      ^\n" +
2132
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2133
		"----------\n" +
2134
		"2. ERROR in X.java (at line 19)\n" +
2135
		"	print(s);\n" +
2136
		"	      ^\n" +
2137
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2138
		"----------\n");
2139
}
2140
// a nonnull variable is dereferenced method of a nested type
2141
public void test_nesting_1() {
2142
	Map customOptions = getCompilerOptions();
2143
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2144
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2145
	runNegativeTestWithLibs(
2146
		new String[] {
2147
			"X.java",
2148
			"import org.eclipse.jdt.annotation.*;\n" +
2149
			"@NonNullByDefault\n" +
2150
			"public class X {\n" +
2151
			"    void print4(final String s1) {\n" +
2152
			"        for (int i=0; i<3; i++)\n" +
2153
			"            new Runnable() {\n" +
2154
			"                public void run() {\n" +
2155
			"                     print(s1);\n" +
2156
			"                }\n" +
2157
			"            }.run();\n" +
2158
			"    }\n" +
2159
			"    void print8(final @Nullable String s2) {\n" +
2160
			"        for (int i=0; i<3; i++)\n" +
2161
			"            new Runnable() {\n" +
2162
			"                public void run() {\n" +
2163
			"                     print(s2);\n" +
2164
			"                }\n" +
2165
			"            }.run();\n" +
2166
			"    }\n" +
2167
			"    void print16(boolean b) {\n" +
2168
			"        final String s3 = b ? null : \"\";\n" +
2169
			"        for (int i=0; i<3; i++)\n" +
2170
			"            new Runnable() {\n" +
2171
			"                public void run() {\n" +
2172
			"                     @NonNull String s3R = s3;\n" +
2173
			"                }\n" +
2174
			"            }.run();\n" +
2175
			"    }\n" +
2176
			"    void print(String s) {\n" +
2177
			"        System.out.print(s);\n" +
2178
			"    }\n" +
2179
			"}\n",
2180
2181
		},
2182
		customOptions,
2183
		"----------\n" +
2184
		"1. ERROR in X.java (at line 16)\n" +
2185
		"	print(s2);\n" +
2186
		"	      ^^\n" +
2187
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2188
		"----------\n" +
2189
		"2. ERROR in X.java (at line 25)\n" +
2190
		"	@NonNull String s3R = s3;\n" +
2191
		"	                      ^^\n" +
2192
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" +
2193
		"----------\n");
2194
}
2195
// Test a regression incurred to the OT/J based implementation
2196
// by the fix in Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
2197
public void test_constructor_with_nested_class() {
2198
	runConformTest(
2199
		new String[] {
2200
			"X.java",
2201
			"public class X {\n" +
2202
			"    final Object o1;\n" +
2203
			"    final Object o2;\n" +
2204
			"    public X() {\n" +
2205
			"         this.o1 = new Object() {\n" +
2206
			"             public String toString() { return \"O1\"; }\n" +
2207
			"         };\n" +
2208
			"         this.o2 = new Object();" +
2209
			"    }\n" +
2210
			"}\n"
2211
		},
2212
		"");
2213
}
2214
}
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java (+2 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
package org.eclipse.jdt.core.tests.compiler.regression;
12
13
Lines 96-101 Link Here
96
	since_1_5.add(InnerEmulationTest_1_5.class);
97
	since_1_5.add(InnerEmulationTest_1_5.class);
97
	since_1_5.add(AssignmentTest_1_5.class);
98
	since_1_5.add(AssignmentTest_1_5.class);
98
	since_1_5.add(InnerClass15Test.class);
99
	since_1_5.add(InnerClass15Test.class);
100
	since_1_5.add(NullAnnotationTest.class);
99
101
100
	// Tests to run when compliance is greater than 1.5
102
	// Tests to run when compliance is greater than 1.5
101
	ArrayList since_1_6 = new ArrayList();
103
	ArrayList since_1_6 = new ArrayList();
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java (-1 / +5 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.dom;
12
package org.eclipse.jdt.core.tests.dom;
12
13
Lines 7494-7500 Link Here
7494
				buffer.append(typeBinding.getAnnotations().length);
7495
				buffer.append(typeBinding.getAnnotations().length);
7495
				typeBinding= typeBinding.getSuperclass();
7496
				typeBinding= typeBinding.getSuperclass();
7496
			}
7497
			}
7497
			assertEquals("Wrong number of annotations", "000", String.valueOf(buffer));
7498
			// initially, this test expected "000", but after https://bugs.eclipse.org/186342
7499
			// annotations are resolved more eagerly, which makes the annotations on Test2 show up,
7500
			// which is actually the right outcome.
7501
			assertEquals("Wrong number of annotations", "020", String.valueOf(buffer));
7498
		}
7502
		}
7499
	}
7503
	}
7500
7504
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java (-1 / +5 lines)
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for 
10
 *     Stephan Herrmann - Contributions for 
11
 *     							Bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
11
 *     							Bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
12
 *     							Bug 353474 - type converters should include more annotations
12
 *     							Bug 353474 - type converters should include more annotations
13
 *     							Bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.core.tests.dom;
15
package org.eclipse.jdt.core.tests.dom;
15
16
Lines 7497-7503 Link Here
7497
				buffer.append(typeBinding.getAnnotations().length);
7498
				buffer.append(typeBinding.getAnnotations().length);
7498
				typeBinding= typeBinding.getSuperclass();
7499
				typeBinding= typeBinding.getSuperclass();
7499
			}
7500
			}
7500
			assertEquals("Wrong number of annotations", "000", String.valueOf(buffer));
7501
			// initially, this test expected "000", but after https://bugs.eclipse.org/186342
7502
			// annotations are resolved more eagerly, which makes the annotations on Test2 show up,
7503
			// which is actually the right outcome.
7504
			assertEquals("Wrong number of annotations", "020", String.valueOf(buffer));
7501
		}
7505
		}
7502
	}
7506
	}
7503
7507
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java (-1 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 185-190 Link Here
185
		UtilTests.class,
185
		UtilTests.class,
186
		
186
		
187
		JavaCoreOptionsTests.class,
187
		JavaCoreOptionsTests.class,
188
		
189
		// Tests regarding null-annotations:
190
		NullAnnotationModelTests.class,
188
	};
191
	};
189
192
190
	Class[] deprecatedClasses = getDeprecatedJDOMTestClasses();
193
	Class[] deprecatedClasses = getDeprecatedJDOMTestClasses();
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java (+418 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 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.model;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.io.StringBufferInputStream;
16
import java.net.URL;
17
import java.util.Hashtable;
18
19
import junit.framework.Test;
20
21
import org.eclipse.core.resources.IFile;
22
import org.eclipse.core.resources.IMarker;
23
import org.eclipse.core.resources.IResource;
24
import org.eclipse.core.resources.IncrementalProjectBuilder;
25
import org.eclipse.core.runtime.CoreException;
26
import org.eclipse.core.runtime.FileLocator;
27
import org.eclipse.core.runtime.Platform;
28
import org.eclipse.jdt.core.ICompilationUnit;
29
import org.eclipse.jdt.core.IJavaModelMarker;
30
import org.eclipse.jdt.core.IJavaProject;
31
import org.eclipse.jdt.core.JavaCore;
32
import org.eclipse.jdt.core.compiler.IProblem;
33
import org.eclipse.jdt.core.dom.AST;
34
import org.eclipse.jdt.core.dom.ASTParser;
35
import org.eclipse.jdt.core.dom.CompilationUnit;
36
37
public class NullAnnotationModelTests extends ReconcilerTests {
38
39
	String ANNOTATION_LIB;
40
41
	public static Test suite() {
42
		return buildModelTestSuite(NullAnnotationModelTests.class);
43
	}
44
45
	public NullAnnotationModelTests(String name) {
46
		super(name);
47
	}
48
49
	static {
50
//		TESTS_NAMES = new String[] { "testMissingAnnotation5" };
51
	}
52
53
	public void setUp() throws Exception {
54
		super.setUp();
55
		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation.null"));
56
		this.ANNOTATION_LIB = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
57
	}
58
59
	protected String testJarPath(String jarName) throws IOException {
60
		URL libEntry = Platform.getBundle("org.eclipse.jdt.core.tests.model").getEntry("/workspace/NullAnnotations/lib/"+jarName);
61
		return FileLocator.toFileURL(libEntry).getPath();
62
	}
63
64
65
	public void testConvertedSourceType1() throws CoreException, InterruptedException {
66
    	try {
67
			// Resources creation
68
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
69
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
70
			p.setOption(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
71
72
			this.createFolder("/P/p1");
73
			String c1SourceString =
74
				"package p1;\n" +
75
				"import org.eclipse.jdt.annotation.*;\n" +
76
				"public class C1 {\n" +
77
				"	 public String foo(@Nullable Object arg) {\n" + // this is consumed via SourceTypeConverter
78
				"		return arg == null ? \"\" : arg.toString();\n" +
79
				"	 }\n" +
80
				"}\n";
81
			this.createFile(
82
				"/P/p1/C1.java",
83
	    			c1SourceString);
84
85
			this.createFolder("/P/p2");
86
			String c2SourceString =
87
				"package p2;\n" +
88
				"public class C2 {\n" +
89
				"	 String bar(p1.C1 c, C2 c2) {;\n" +
90
				"        return c.foo(null);\n" + // don't complain despite default nonnull, foo has explicit @Nullable
91
				"    }\n" +
92
				"	 String foo(Object arg) {\n" +
93
				"		return arg == null ? null : arg.toString();\n" +
94
				"	 }\n" +
95
				"}\n";
96
			this.createFile(
97
				"/P/p2/C2.java",
98
	    			c2SourceString);
99
100
			char[] c2SourceChars = c2SourceString.toCharArray();
101
			this.problemRequestor.initialize(c2SourceChars);
102
103
			getCompilationUnit("/P/p2/C2.java").getWorkingCopy(this.wcOwner, null);
104
105
			assertProblems("Unexpected problems", "----------\n" +
106
					"1. WARNING in /P/p2/C2.java (at line 7)\n" +
107
					"	return arg == null ? null : arg.toString();\n" +
108
					"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
109
					"Potential type mismatch: required \'@NonNull String\' but nullness of the provided value is unknown\n" +
110
					"----------\n");
111
    	} finally {
112
    		deleteProject("P");
113
    	}
114
    }
115
116
	public void testBinaryType1() throws CoreException, InterruptedException, IOException {
117
    	try {
118
			// Resources creation
119
			IJavaProject p = createJavaProject("P", new String[] {""},
120
											   new String[] {"JCL15_LIB", this.ANNOTATION_LIB, testJarPath("example.jar")},
121
											   "bin", "1.5");
122
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
123
			p.setOption(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
124
125
			// example.jar contains p1/C1.java just like testConvertedSourceType1()
126
127
			this.createFolder("/P/p2");
128
			String c2SourceString =
129
				"package p2;\n" +
130
				"public class C2 {\n" +
131
				"	 String bar(p1.C1 c) {;\n" +
132
				"        return c.foo(null);\n" + // don't complain despite default nonnull, foo has explicit @Nullable
133
				"    }\n" +
134
				"	 String foo(Object arg) {\n" +
135
				"		return arg == null ? null : arg.toString();\n" +
136
				"	 }\n" +
137
				"}\n";
138
			this.createFile(
139
				"/P/p2/C2.java",
140
	    			c2SourceString);
141
142
			char[] c2SourceChars = c2SourceString.toCharArray();
143
			this.problemRequestor.initialize(c2SourceChars);
144
145
			getCompilationUnit("/P/p2/C2.java").getWorkingCopy(this.wcOwner, null);
146
147
			assertProblems("Unexpected problems", "----------\n" +
148
					"1. WARNING in /P/p2/C2.java (at line 7)\n" +
149
					"	return arg == null ? null : arg.toString();\n" +
150
					"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
151
					"Potential type mismatch: required \'@NonNull String\' but nullness of the provided value is unknown\n" +
152
					"----------\n");
153
    	} finally {
154
    		deleteProject("P");
155
    	}
156
    }
157
158
	public void testMissingAnnotation1() throws CoreException {
159
    	try {
160
			// Resources creation
161
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
162
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
163
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "in.valid");
164
165
			this.createFolder("/P/p1");
166
			String c1SourceString =
167
				"package p1;\n" +
168
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
169
				"public class C1 {\n" +
170
				"	 public String foo(Object arg) {\n" +
171
				"		return arg == null ? \"\" : arg.toString();\n" +
172
				"	 }\n" +
173
				"}\n";
174
			this.createFile(
175
				"/P/p1/C1.java",
176
	    			c1SourceString);
177
178
			this.problemRequestor.initialize(c1SourceString.toCharArray());
179
180
			getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
181
182
			assertProblems("Unexpected problems",
183
					"----------\n" +
184
					"1. ERROR in /P/p1/C1.java (at line 1)\n" +
185
					"	package p1;\n" +
186
					"	^\n" +
187
					"Buildpath problem: the type in.valid, which is configured as a null annotation type, cannot be resolved\n" +
188
					"----------\n");
189
    	} finally {
190
    		deleteProject("P");
191
    	}
192
	}
193
194
	public void testMissingAnnotation2() throws CoreException {
195
		Hashtable javaOptions = JavaCore.getOptions();
196
    	try {
197
			// Resources creation
198
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
199
			IFile settings = (IFile) p.getProject().findMember(".settings/org.eclipse.jdt.core.prefs");
200
			settings.appendContents(new StringBufferInputStream("\norg.eclipse.jdt.core.compiler.annotation.nonnull=not.valid\n"), 0, null);
201
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
202
203
			this.createFolder("/P/p1");
204
			String c1SourceString =
205
				"package p1;\n" +
206
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
207
				"public class C1 {\n" +
208
				"	 public String foo(Object arg) {\n" +
209
				"		return arg == null ? \"\" : arg.toString();\n" +
210
				"	 }\n" +
211
				"}\n";
212
			this.createFile(
213
				"/P/p1/C1.java",
214
	    			c1SourceString);
215
216
			this.problemRequestor.initialize(c1SourceString.toCharArray());
217
218
			getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
219
220
			assertProblems("Unexpected problems",
221
					"----------\n" +
222
					"1. ERROR in /P/p1/C1.java (at line 1)\n" +
223
					"	package p1;\n" +
224
					"	^\n" +
225
					"Buildpath problem: the type not.valid, which is configured as a null annotation type, cannot be resolved\n" +
226
					"----------\n");
227
    	} finally {
228
    		deleteProject("P");
229
    		JavaCore.setOptions(javaOptions);
230
    		// work against side-effect of JavaRuntime listening to change of prefs-file.
231
    		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=302850#c25
232
    	}
233
	}
234
235
	// Bug 363858 - [dom] early throwing of AbortCompilation causes NPE in CompilationUnitResolver
236
	// currently not actually challenging the NPE, because we no longer report
237
	// "Cannot use the unqualified name \'invalid\' as an annotation name for null specification"
238
	public void testMissingAnnotation3() throws CoreException {
239
    	try {
240
			// Resources creation
241
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
242
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
243
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "invalid");
244
245
			this.createFolder("/P/p1");
246
			String c1SourceString =
247
				"package p1;\n" +
248
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
249
				"public class C1 {\n" +
250
				"	 public String foo(Object arg) {\n" +
251
				"		return arg == null ? \"\" : arg.toString();\n" +
252
				"	 }\n" +
253
				"}\n";
254
			this.createFile(
255
				"/P/p1/C1.java",
256
	    			c1SourceString);
257
258
			this.problemRequestor.initialize(c1SourceString.toCharArray());
259
260
			final ICompilationUnit unit = getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
261
			assertProblems("Unexpected problems",
262
					"----------\n" +
263
					"1. ERROR in /P/p1/C1.java (at line 1)\n" +
264
					"	package p1;\n" +
265
					"	^\n" +
266
					"Buildpath problem: the type invalid, which is configured as a null annotation type, cannot be resolved\n" +
267
					"----------\n");
268
269
			ASTParser parser = ASTParser.newParser(AST.JLS4);
270
			parser.setProject(p);
271
			parser.setResolveBindings(true);
272
			parser.setSource(unit);
273
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
274
			assertNotNull("ast should not be null", ast);
275
			this.problemRequestor.reset();
276
			this.problemRequestor.beginReporting();
277
			IProblem[] problems = ast.getProblems();
278
			for (int i=0; i<problems.length; i++)
279
				this.problemRequestor.acceptProblem(problems[i]);
280
			assertProblems("Unexpected problems (2)",
281
					"----------\n" +
282
					"1. ERROR in /P/p1/C1.java (at line 1)\n" +
283
					"	package p1;\n" +
284
					"	^\n" +
285
					"Buildpath problem: the type invalid, which is configured as a null annotation type, cannot be resolved\n" +
286
					"----------\n");
287
    	} finally {
288
    		deleteProject("P");
289
    	}
290
	}
291
292
	// initialization of null annotations is triggered from package-info.java: illegal simple name
293
	public void testMissingAnnotation4() throws CoreException, InterruptedException {
294
    	try {
295
			// Resources creation
296
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
297
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
298
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "invalid");
299
300
			this.createFolder("/P/p1");
301
			String piSourceString =
302
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
303
				"package p1;\n";
304
			this.createFile(
305
				"/P/p1/package-info.java",
306
	    			piSourceString);
307
308
			this.problemRequestor.initialize(piSourceString.toCharArray());
309
310
			// Challenge CompilationUnitProblemFinder:
311
			final ICompilationUnit unit = getCompilationUnit("/P/p1/package-info.java").getWorkingCopy(this.wcOwner, null);
312
// This error is not raised currently:
313
//			String expectedError = "----------\n" +
314
//								   "1. ERROR in /P/p1/package-info.java (at line 0)\n" +
315
//								   "	@org.eclipse.jdt.annotation.NonNullByDefault\n" +
316
//								   "	^\n" +
317
//								   "Cannot use the unqualified name \'invalid\' as an annotation name for null specification\n" +
318
//								   "----------\n";
319
//			assertProblems("Unexpected problems from CompilationUnitProblemFinder", expectedError);
320
			assertNoProblem(unit.getBuffer().getCharacters(), unit);
321
322
			// Challenge JavaBuilder:
323
			p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
324
			IMarker[] markers = p.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
325
//			assertMarkers("Unexpected markers",
326
//					"Cannot use the unqualified name 'invalid' as an annotation name for null specification",
327
//					markers);
328
//			assertEquals("Unexpected marker path", "/P", markers[0].getResource().getFullPath().toString());
329
			assertEquals("Should have no markers", 0, markers.length);
330
331
			// Challenge CompilationUnitResolver:
332
			ASTParser parser = ASTParser.newParser(AST.JLS4);
333
			parser.setProject(p);
334
			parser.setResolveBindings(true);
335
			parser.setSource(unit);
336
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
337
			assertNotNull("ast should not be null", ast);
338
//			this.problemRequestor.reset();
339
//			this.problemRequestor.beginReporting();
340
//			IProblem[] problems = ast.getProblems();
341
//			for (int i=0; i<problems.length; i++)
342
//				this.problemRequestor.acceptProblem(problems[i]);
343
//			assertProblems("Unexpected problems from CompilationUnitResolver", expectedError);
344
			assertEquals("Should have no problems", 0, ast.getProblems().length);
345
    	} finally {
346
    		deleteProject("P");
347
    	}
348
	}
349
350
	// initialization of null annotations is
351
	// - triggered from resolveTypesFor(MethodBinding)
352
	// - default is defined in package-info.java:
353
	// must detect missing non-null annotation and report against the project
354
	public void testMissingAnnotation5() throws CoreException, InterruptedException {
355
    	try {
356
			// Resources creation
357
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
358
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
359
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "pack.Missing");
360
361
			this.createFolder("/P/p1");
362
			String piSourceString =
363
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
364
				"package p1;\n";
365
			this.createFile("/P/p1/package-info.java", piSourceString);
366
367
			String c1SourceString =
368
				"package p1;\n" +
369
				"public class C1 {\n" +
370
				"    String foo(String arg) { return arg; }\n" +
371
				"}\n";
372
			this.createFile("/P/p1/C1.java", c1SourceString);
373
374
			this.problemRequestor.initialize(piSourceString.toCharArray());
375
376
			// Challenge CompilationUnitProblemFinder:
377
			assertNoProblem(piSourceString.toCharArray(), getCompilationUnit("/P/p1/package-info.java"));
378
379
			this.problemRequestor.initialize(c1SourceString.toCharArray());
380
381
			// Challenge CompilationUnitProblemFinder:
382
			ICompilationUnit unit = getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
383
			String expectedError = "----------\n" +
384
								   "1. ERROR in /P/p1/C1.java (at line 1)\n" +
385
								   "	package p1;\n" +
386
								   "	^\n" +
387
								   "Buildpath problem: the type pack.Missing, which is configured as a null annotation type, cannot be resolved\n" +
388
								   "----------\n";
389
			assertProblems("Unexpected problems", expectedError);
390
391
			// Challenge JavaBuilder:
392
			p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
393
			IMarker[] markers = p.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
394
			assertMarkers("Unexpected markers",
395
					"Buildpath problem: the type pack.Missing, which is configured as a null annotation type, cannot be resolved",
396
					markers);
397
// toggle expectation depending on how CAT_BUILDPATH problems are reported (see AbstractImageBuilder.storeProblemsFor(..))
398
//			assertEquals("Unexpected marker path", "/P", markers[0].getResource().getFullPath().toString());
399
			assertEquals("Unexpected marker path", "/P/p1/C1.java", markers[0].getResource().getFullPath().toString());
400
401
			// Challenge CompilationUnitResolver:
402
			ASTParser parser = ASTParser.newParser(AST.JLS4);
403
			parser.setProject(p);
404
			parser.setResolveBindings(true);
405
			parser.setSource(unit);
406
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
407
			assertNotNull("ast should not be null", ast);
408
			this.problemRequestor.reset();
409
			this.problemRequestor.beginReporting();
410
			IProblem[] problems = ast.getProblems();
411
			for (int i=0; i<problems.length; i++)
412
				this.problemRequestor.acceptProblem(problems[i]);
413
			assertProblems("Unexpected problems (2)", expectedError);
414
    	} finally {
415
    		deleteProject("P");
416
    	}
417
	}
418
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java (+46 lines)
Added Link Here
122
 *									UnclosedCloseable
122
 *									UnclosedCloseable
123
 *									UnclosedCloseableAtExit
123
 *									UnclosedCloseableAtExit
124
 *									ExplicitlyClosedAutoCloseable
124
 *									ExplicitlyClosedAutoCloseable
125
 * 								    RequiredNonNullButProvidedNull
126
 * 									RequiredNonNullButProvidedPotentialNull
127
 * 									RequiredNonNullButProvidedUnknown
128
 * 									MissingNullAnnotationType
129
 * 									NullAnnotationNameMustBeQualified
130
 * 									IllegalReturnNullityRedefinition
131
 * 									IllegalRedefinitionToNonNullParameter
132
 * 									IllegalDefinitionToNonNullParameter
133
 * 									ParameterLackingNonNullAnnotation
134
 * 									ParameterLackingNullableAnnotation
135
 * 									PotentialNullMessageSendReference
136
 * 									RedundantNullCheckOnNonNullMessageSend
137
 * 									CannotImplementIncompatibleNullness
138
 * 									RedundantNullAnnotation
125
 *******************************************************************************/
139
 *******************************************************************************/
126
package org.eclipse.jdt.core.compiler;
140
package org.eclipse.jdt.core.compiler;
127
141
Added Link Here
1416
	/** @since 3.8 */
1430
	/** @since 3.8 */
1417
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1431
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1418
	/**
1432
	/**
1433
	 * Errors/warnings from annotation based null analysis
1434
	 */
1435
	/** @since 3.8 */
1436
	int RequiredNonNullButProvidedNull = TypeRelated + 910;
1437
	/** @since 3.8 */
1438
	int RequiredNonNullButProvidedPotentialNull = TypeRelated + 911;
1439
	/** @since 3.8 */
1440
	int RequiredNonNullButProvidedUnknown = TypeRelated + 912;
1441
	/** @since 3.8 */
1442
	int MissingNullAnnotationType = ImportRelated + 913;
1443
	/** @since 3.8 */
1444
	int IllegalReturnNullityRedefinition = MethodRelated + 914;
1445
	/** @since 3.8 */
1446
	int IllegalRedefinitionToNonNullParameter = MethodRelated + 915;
1447
	/** @since 3.8 */
1448
	int IllegalDefinitionToNonNullParameter = MethodRelated + 916;
1449
	/** @since 3.8 */
1450
	int ParameterLackingNonNullAnnotation = MethodRelated + 917;
1451
	/** @since 3.8 */
1452
	int ParameterLackingNullableAnnotation = MethodRelated + 918;
1453
	/** @since 3.8 */
1454
	int PotentialNullMessageSendReference = Internal + 919;
1455
	/** @since 3.8 */
1456
	int RedundantNullCheckOnNonNullMessageSend = Internal + 920;
1457
	/** @since 3.8 */
1458
	int CannotImplementIncompatibleNullness = Internal + 921;
1459
	/** @since 3.8 */
1460
	int RedundantNullAnnotation = MethodRelated + 922;
1461
	/** @since 3.8 */
1462
	int IllegalAnnotationForBaseType = TypeRelated + 923;
1463
1464
	/**
1419
	 * External problems -- These are problems defined by other plugins
1465
	 * External problems -- These are problems defined by other plugins
1420
	 */
1466
	 */
1421
1467
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java (-3 / +10 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - contribution for bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
10
 *     Stephan Herrmann - contributions for 
11
 *     							bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
12
 *     							bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler;
14
package org.eclipse.jdt.internal.compiler;
13
15
Lines 695-700 Link Here
695
697
696
		// Switch the current policy and compilation result for this unit to the requested one.
698
		// Switch the current policy and compilation result for this unit to the requested one.
697
		for (int i = 0; i < maxUnits; i++) {
699
		for (int i = 0; i < maxUnits; i++) {
700
			CompilationResult unitResult = null;
698
			try {
701
			try {
699
				if (this.options.verbose) {
702
				if (this.options.verbose) {
700
					this.out.println(
703
					this.out.println(
Lines 707-714 Link Here
707
				}
710
				}
708
				// diet parsing for large collection of units
711
				// diet parsing for large collection of units
709
				CompilationUnitDeclaration parsedUnit;
712
				CompilationUnitDeclaration parsedUnit;
710
				CompilationResult unitResult =
713
				unitResult = new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
711
					new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
712
				long parseStart = System.currentTimeMillis();
714
				long parseStart = System.currentTimeMillis();
713
				if (this.totalUnits < this.parseThreshold) {
715
				if (this.totalUnits < this.parseThreshold) {
714
					parsedUnit = this.parser.parse(sourceUnits[i], unitResult);
716
					parsedUnit = this.parser.parse(sourceUnits[i], unitResult);
Lines 727-732 Link Here
727
				}
729
				}
728
				//} catch (AbortCompilationUnit e) {
730
				//} catch (AbortCompilationUnit e) {
729
				//	requestor.acceptResult(unitResult.tagAsAccepted());
731
				//	requestor.acceptResult(unitResult.tagAsAccepted());
732
			} catch (AbortCompilation a) {
733
				// best effort to find a way for reporting this problem:
734
				if (a.compilationResult == null)
735
					a.compilationResult = unitResult;
736
				throw a;
730
			} finally {
737
			} finally {
731
				sourceUnits[i] = null; // no longer hold onto the unit
738
				sourceUnits[i] = null; // no longer hold onto the unit
732
			}
739
			}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (-2 / +9 lines)
Lines 9-15 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995
10
 *     Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995
11
 *     Karen Moore - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=207411
11
 *     Karen Moore - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=207411
12
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
12
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
13
 *     							bug 185682 - Increment/decrement operators mark local variables as read
14
 *     							bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
15
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
15
17
Lines 253-258 Link Here
253
255
254
	// this is only used for method invocation as the expression inside an expression statement
256
	// this is only used for method invocation as the expression inside an expression statement
255
	public static final int InsideExpressionStatement = Bit5;
257
	public static final int InsideExpressionStatement = Bit5;
258
259
	// for annotation reference, signal if annotation was created from a default:
260
	public static final int IsSynthetic = ASTNode.Bit7;
261
	// for name reference within a memberValuePair of an annotation:
262
	public static final int IsMemberValueReference = ASTNode.Bit15;
256
263
257
	public ASTNode() {
264
	public ASTNode() {
258
265
Lines 601-607 Link Here
601
					local.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
608
					local.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
602
					if (length > 0) {
609
					if (length > 0) {
603
						annotations = new AnnotationBinding[length];
610
						annotations = new AnnotationBinding[length];
604
						local.setAnnotations(annotations);
611
						local.setAnnotations(annotations, scope);
605
					}
612
					}
606
					break;
613
					break;
607
				default :
614
				default :
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java (+95 lines)
Lines 7-17 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
14
import java.util.Arrays;
15
13
import org.eclipse.jdt.core.compiler.*;
16
import org.eclipse.jdt.core.compiler.*;
14
import org.eclipse.jdt.internal.compiler.*;
17
import org.eclipse.jdt.internal.compiler.*;
18
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
15
import org.eclipse.jdt.internal.compiler.impl.*;
19
import org.eclipse.jdt.internal.compiler.impl.*;
16
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17
import org.eclipse.jdt.internal.compiler.codegen.*;
21
import org.eclipse.jdt.internal.compiler.codegen.*;
Lines 64-69 Link Here
64
				throw new AbortType(this.compilationResult, problem);
68
				throw new AbortType(this.compilationResult, problem);
65
			default :
69
			default :
66
				throw new AbortMethod(this.compilationResult, problem);
70
				throw new AbortMethod(this.compilationResult, problem);
71
		}
72
	}
73
74
	/**
75
	 * Materialize a null annotation that has been added from the current default,
76
	 * in order to ensure that this annotation will be generated into the .class file, too.
77
	 */
78
	public void addNullnessAnnotation(ReferenceBinding annotationBinding) {
79
		this.annotations = addAnnotation(this, this.annotations, annotationBinding);
80
	}
81
82
	/**
83
	 * Materialize a null parameter annotation that has been added from the current default,
84
	 * in order to ensure that this annotation will be generated into the .class file, too.
85
	 */
86
	public void addParameterNonNullAnnotation(int i, ReferenceBinding annotationBinding) {
87
		Argument argument = this.arguments[i];
88
		if (argument.type != null) // null happens for constructors of anonymous classes
89
			argument.annotations = addAnnotation(argument.type, argument.annotations, annotationBinding);
90
	}
91
92
	private Annotation[] addAnnotation(ASTNode location, Annotation[] oldAnnotations, ReferenceBinding annotationBinding) {
93
		long pos = ((long)location.sourceStart<<32) + location.sourceEnd;
94
		long[] poss = new long[annotationBinding.compoundName.length];
95
		Arrays.fill(poss, pos);
96
		MarkerAnnotation annotation = new MarkerAnnotation(new QualifiedTypeReference(annotationBinding.compoundName, poss), location.sourceStart);
97
		annotation.declarationSourceEnd = location.sourceEnd;
98
		annotation.resolvedType = annotationBinding;
99
		annotation.bits = IsSynthetic;
100
		if (oldAnnotations == null) {
101
			oldAnnotations = new Annotation[] {annotation};
102
		} else {
103
			int len = oldAnnotations.length;
104
			System.arraycopy(oldAnnotations, 0, oldAnnotations=new Annotation[len+1], 1, len);
105
			oldAnnotations[0] = annotation;
106
		}
107
		return oldAnnotations;
108
	}
109
110
	/**
111
	 * When a method is accessed via SourceTypeBinding.resolveTypesFor(MethodBinding)
112
	 * we create the argument binding and resolve annotations in order to compute null annotation tagbits.
113
	 */
114
	public void createArgumentBindings() {
115
		if (this.arguments != null && this.binding != null) {
116
			for (int i = 0, length = this.arguments.length; i < length; i++) {
117
				Argument argument = this.arguments[i];
118
				argument.createBinding(this.scope, this.binding.parameters[i]);
119
				// createBinding() has resolved annotations, now transfer nullness info from the argument to the method:
120
				if ((argument.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0) {
121
					if (this.binding.parameterNonNullness == null)
122
						this.binding.parameterNonNullness = new Boolean[this.arguments.length];
123
					this.binding.parameterNonNullness[i] = Boolean.valueOf((argument.binding.tagBits & TagBits.AnnotationNonNull) != 0);
124
				}
125
			}
67
		}
126
		}
68
	}
127
	}
69
128
Lines 139-144 Link Here
139
						}
198
						}
140
					}
199
					}
141
				}
200
				}
201
			}
202
		}
203
	}
204
205
	/**
206
	 * Feed null information from argument annotations into the analysis and mark arguments as assigned.
207
	 */
208
	void analyseArguments(FlowInfo flowInfo) {
209
		if (this.arguments != null) {
210
			for (int i = 0, count = this.arguments.length; i < count; i++) {
211
				if (this.binding.parameterNonNullness != null) {
212
					// leverage null-info from parameter annotations:
213
					Boolean nonNullNess = this.binding.parameterNonNullness[i];
214
					if (nonNullNess != null) {
215
						if (nonNullNess.booleanValue())
216
							flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
217
						else
218
							flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
219
					}
220
				}
221
				// tag parameters as being set:
222
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
142
			}
223
			}
143
		}
224
		}
144
	}
225
	}
Lines 415-420 Link Here
415
			bindThrownExceptions();
496
			bindThrownExceptions();
416
			resolveJavadoc();
497
			resolveJavadoc();
417
			resolveAnnotations(this.scope, this.annotations, this.binding);
498
			resolveAnnotations(this.scope, this.annotations, this.binding);
499
			validateAnnotations();
418
			resolveStatements();
500
			resolveStatements();
419
			// check @Deprecated annotation presence
501
			// check @Deprecated annotation presence
420
			if (this.binding != null
502
			if (this.binding != null
Lines 478-481 Link Here
478
	public TypeParameter[] typeParameters() {
560
	public TypeParameter[] typeParameters() {
479
	    return null;
561
	    return null;
480
	}
562
	}
563
564
	void validateAnnotations() {
565
		// null annotations on parameters?
566
		if (this.binding != null && this.binding.parameterNonNullness != null) {
567
			for (int i=0; i<this.binding.parameters.length; i++) {
568
				if (this.binding.parameterNonNullness[i] != null) {
569
					long nullAnnotationTagBit =  this.binding.parameterNonNullness[i].booleanValue()
570
							? TagBits.AnnotationNonNull : TagBits.AnnotationNullable;
571
					this.scope.validateNullAnnotation(nullAnnotationTagBit, this.arguments[i].type, this.arguments[i].annotations);
572
				}
573
			}
574
		}
575
	}
481
}
576
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-1 / +3 lines)
Lines 7-16 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for 
10
 *     Stephan Herrmann - Contributions for
11
 *     						bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
11
 *     						bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
14
 * 							bug 186342 - [compiler][null] Using annotations for null checking
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
16
17
Lines 53-58 Link Here
53
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
54
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
54
			}
55
			}
55
		}
56
		}
57
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
56
	}
58
	}
57
	// record some dependency information for exception types
59
	// record some dependency information for exception types
58
	ReferenceBinding[] thrownExceptions;
60
	ReferenceBinding[] thrownExceptions;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java (+17 lines)
Lines 7-12 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 173-178 Link Here
173
			case TypeIds.T_JavaxAnnotationPreDestroy :
174
			case TypeIds.T_JavaxAnnotationPreDestroy :
174
				tagBits |= TagBits.AnnotationPreDestroy;
175
				tagBits |= TagBits.AnnotationPreDestroy;
175
				break;
176
				break;
177
			case TypeIds.T_ConfiguredAnnotationNullable :
178
				tagBits |= TagBits.AnnotationNullable;
179
				break;
180
			case TypeIds.T_ConfiguredAnnotationNonNull :
181
				tagBits |= TagBits.AnnotationNonNull;
182
				break;
183
			case TypeIds.T_ConfiguredAnnotationNonNullByDefault :
184
				if (valueAttribute != null 
185
					&& valueAttribute.value instanceof FalseLiteral) 
186
				{
187
					// parameter 'false' means: this annotation cancels any defaults
188
					tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
189
					break;
190
				}
191
				tagBits |= TagBits.AnnotationNonNullByDefault;
192
				break;
176
		}
193
		}
177
		return tagBits;
194
		return tagBits;
178
	}
195
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java (-15 / +20 lines)
Lines 4-12 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 30-36 Link Here
30
		this.bits |= (IsLocalDeclarationReachable | IsArgument);
31
		this.bits |= (IsLocalDeclarationReachable | IsArgument);
31
	}
32
	}
32
33
34
	public void createBinding(MethodScope scope, TypeBinding typeBinding) {
35
		if (this.binding == null) {
36
			// for default constructors and fake implementation of abstract methods 
37
			this.binding = new LocalVariableBinding(this, typeBinding, this.modifiers, true);
38
		} else if (!this.binding.type.isValidBinding()) {
39
			AbstractMethodDeclaration methodDecl = scope.referenceMethod();
40
			if (methodDecl != null) {
41
				MethodBinding methodBinding = methodDecl.binding;
42
				if (methodBinding != null) {
43
					methodBinding.tagBits |= TagBits.HasUnresolvedArguments;
44
				}
45
			}
46
		}
47
		resolveAnnotations(scope, this.annotations, this.binding);
48
		this.binding.declaration = this;
49
	}
50
33
	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
51
	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
52
		createBinding(scope, typeBinding); // basically a no-op if createBinding() was called before
34
53
35
		// record the resolved type into the type reference
54
		// record the resolved type into the type reference
36
		Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
55
		Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
Lines 52-73 Link Here
52
				scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument);
71
				scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument);
53
			}
72
			}
54
		}
73
		}
55
56
		if (this.binding == null) {
57
			this.binding = new LocalVariableBinding(this, typeBinding, this.modifiers, true);
58
		} else if (!this.binding.type.isValidBinding()) {
59
			AbstractMethodDeclaration methodDecl = scope.referenceMethod();
60
			if (methodDecl != null) {
61
				MethodBinding methodBinding = methodDecl.binding;
62
				if (methodBinding != null) {
63
					methodBinding.tagBits |= TagBits.HasUnresolvedArguments;
64
				}
65
			}
66
		}
67
		scope.addLocalVariable(this.binding);
74
		scope.addLocalVariable(this.binding);
68
		resolveAnnotations(scope, this.annotations, this.binding);
69
		//true stand for argument instead of just local
75
		//true stand for argument instead of just local
70
		this.binding.declaration = this;
71
		this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
76
		this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
72
	}
77
	}
73
78
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-3 / +4 lines)
Lines 4-18 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Genady Beriozkin - added support for reporting assignment with no effect
10
 *     Genady Beriozkin - added support for reporting assignment with no effect
11
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
11
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
12
 * 							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 * 							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 * 							bug 292478 - Report potentially null across variable assignment
13
 * 							bug 292478 - Report potentially null across variable assignment
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
16
 *							bug 186342 - [compiler][null] Using annotations for null checking
16
 *******************************************************************************/
17
 *******************************************************************************/
17
package org.eclipse.jdt.internal.compiler.ast;
18
package org.eclipse.jdt.internal.compiler.ast;
18
19
Lines 65-71 Link Here
65
				FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
66
				FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
66
		}
67
		}
67
	}
68
	}
68
	nullStatus = checkAgainstNullAnnotation(currentScope, local, nullStatus);
69
	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, local, nullStatus, this.expression);
69
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
70
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
70
		flowInfo.markNullStatus(local, nullStatus);
71
		flowInfo.markNullStatus(local, nullStatus);
71
		if (flowContext.initsOnFinally != null)
72
		if (flowContext.initsOnFinally != null)
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (-7 / +4 lines)
Lines 7-15 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for 
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance
11
 *     							bug 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.ast;
15
package org.eclipse.jdt.internal.compiler.ast;
15
16
Lines 113-124 Link Here
113
			}
114
			}
114
		}
115
		}
115
116
116
		// tag parameters as being set
117
		// nullity and mark as assigned
117
		if (this.arguments != null) {
118
		analyseArguments(flowInfo);
118
			for (int i = 0, count = this.arguments.length; i < count; i++) {
119
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
120
			}
121
		}
122
119
123
		// propagate to constructor call
120
		// propagate to constructor call
124
		if (this.constructorCall != null) {
121
		if (this.constructorCall != null) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java (-1 / +17 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 23-28 Link Here
23
		super(left,right,operator);
24
		super(left,right,operator);
24
	}
25
	}
25
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
26
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
27
		// check sends to null-annotated methods:
28
		MessageSend leftMessage = (this.left instanceof MessageSend) ? (MessageSend) this.left : null;
29
		if (   leftMessage != null 
30
			&& leftMessage.nullStatus(flowInfo) == FlowInfo.NON_NULL
31
			&& this.right.nullStatus(flowInfo) == FlowInfo.NULL) 
32
		{
33
			scope.problemReporter().messageSendRedundantCheckOnNonNull(leftMessage.binding, leftMessage);
34
		}
35
		MessageSend rightMessage = (this.right instanceof MessageSend) ? (MessageSend) this.right : null;
36
		if (   rightMessage != null 
37
			&& rightMessage.nullStatus(flowInfo) == FlowInfo.NON_NULL 
38
			&& this.left.nullStatus(flowInfo) == FlowInfo.NULL) 
39
		{
40
			scope.problemReporter().messageSendRedundantCheckOnNonNull(rightMessage.binding, rightMessage);
41
		}
26
42
27
		LocalVariableBinding local = this.left.localVariableBinding();
43
		LocalVariableBinding local = this.left.localVariableBinding();
28
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
44
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java (-1 / +4 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.ast;
14
package org.eclipse.jdt.internal.compiler.ast;
13
15
Lines 81-86 Link Here
81
						this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
83
						this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
82
					}
84
					}
83
				}
85
				}
86
				analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
84
			}
87
			}
85
88
86
			ReferenceBinding[] thrownExceptions;
89
			ReferenceBinding[] thrownExceptions;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-2 / +4 lines)
Lines 7-17 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
11
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
11
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     						bug 292478 - Report potentially null across variable assignment
12
 *     						bug 292478 - Report potentially null across variable assignment
13
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
13
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
15
 *							bug 186342 - [compiler][null] Using annotations for null checking
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 85-91 Link Here
85
		this.bits &= ~FirstAssignmentToLocal;  // int i = (i = 0);
86
		this.bits &= ~FirstAssignmentToLocal;  // int i = (i = 0);
86
	}
87
	}
87
	flowInfo.markAsDefinitelyAssigned(this.binding);
88
	flowInfo.markAsDefinitelyAssigned(this.binding);
88
	nullStatus = checkAgainstNullAnnotation(currentScope, this.binding, nullStatus);		
89
	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, this.binding, nullStatus, this.initialization);
89
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
90
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
90
		flowInfo.markNullStatus(this.binding, nullStatus);
91
		flowInfo.markNullStatus(this.binding, nullStatus);
91
		// no need to inform enclosing try block since its locals won't get
92
		// no need to inform enclosing try block since its locals won't get
Lines 250-255 Link Here
250
		}
251
		}
251
		// only resolve annotation at the end, for constant to be positioned before (96991)
252
		// only resolve annotation at the end, for constant to be positioned before (96991)
252
		resolveAnnotations(scope, this.annotations, this.binding);
253
		resolveAnnotations(scope, this.annotations, this.binding);
254
		scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations);
253
	}
255
	}
254
256
255
	public void traverse(ASTVisitor visitor, BlockScope scope) {
257
	public void traverse(ASTVisitor visitor, BlockScope scope) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java (-1 / +5 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 41-46 Link Here
41
		if (value instanceof ArrayInitializer) {
42
		if (value instanceof ArrayInitializer) {
42
			value.bits |= IsAnnotationDefaultValue;
43
			value.bits |= IsAnnotationDefaultValue;
43
		}
44
		}
45
		if (value instanceof NameReference) {
46
			value.bits |= IsMemberValueReference;
47
		}
44
	}
48
	}
45
49
46
	/* (non-Javadoc)
50
	/* (non-Javadoc)
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-1 / +15 lines)
Lines 11-16 Link Here
11
 *     Stephan Herrmann - Contributions for
11
 *     Stephan Herrmann - Contributions for
12
 *     	 						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     	 						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
16
17
Lines 99-104 Link Here
99
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
100
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
100
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
		}
102
		}
103
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
102
	}
104
	}
103
	ReferenceBinding[] thrownExceptions;
105
	ReferenceBinding[] thrownExceptions;
104
	if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
106
	if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
Lines 114-119 Link Here
114
	}
116
	}
115
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
117
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
116
	return flowInfo;
118
	return flowInfo;
119
}
120
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
121
	super.checkNPE(scope, flowContext, flowInfo);
122
	if (nullStatus(flowInfo) == FlowInfo.POTENTIALLY_NULL)
123
		scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
117
}
124
}
118
/**
125
/**
119
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
126
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
Lines 268-276 Link Here
268
	}
275
	}
269
}
276
}
270
public int nullStatus(FlowInfo flowInfo) {
277
public int nullStatus(FlowInfo flowInfo) {
278
	if (this.binding.isValidBinding()) {
279
		// try to retrieve null status of this message send from an annotation of the called method:
280
		long tagBits = this.binding.tagBits;
281
		if ((tagBits & TagBits.AnnotationNonNull) != 0)
282
			return FlowInfo.NON_NULL;
283
		if ((tagBits & TagBits.AnnotationNullable) != 0)
284
			return FlowInfo.POTENTIALLY_NULL;
285
	}
271
	return FlowInfo.UNKNOWN;
286
	return FlowInfo.UNKNOWN;
272
}
287
}
273
274
/**
288
/**
275
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
289
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
276
 */
290
 */
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (-3 / +13 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.ast;
14
package org.eclipse.jdt.internal.compiler.ast;
13
15
Lines 79-88 Link Here
79
					this.scope,
81
					this.scope,
80
					FlowInfo.DEAD_END);
82
					FlowInfo.DEAD_END);
81
83
82
			// tag parameters as being set
84
			// nullity and mark as assigned
85
			analyseArguments(flowInfo);
86
83
			if (this.arguments != null) {
87
			if (this.arguments != null) {
84
				for (int i = 0, count = this.arguments.length; i < count; i++) {
88
				for (int i = 0, count = this.arguments.length; i < count; i++) {
85
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
86
					// if this method uses a type parameter declared by the declaring class,
89
					// if this method uses a type parameter declared by the declaring class,
87
					// it can't be static. https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
90
					// it can't be static. https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
88
					if (this.arguments[i].binding != null && (this.arguments[i].binding.type instanceof TypeVariableBinding)) {
91
					if (this.arguments[i].binding != null && (this.arguments[i].binding.type instanceof TypeVariableBinding)) {
Lines 307-310 Link Here
307
	public TypeParameter[] typeParameters() {
310
	public TypeParameter[] typeParameters() {
308
	    return this.typeParameters;
311
	    return this.typeParameters;
309
	}
312
	}
313
	
314
	void validateAnnotations() {
315
		super.validateAnnotations();
316
		// null-annotations on the return type?
317
		if (this.binding != null)
318
			this.scope.validateNullAnnotation(this.binding.tagBits, this.returnType, this.annotations);
319
	}
310
}
320
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (+2 lines)
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.ast;
15
package org.eclipse.jdt.internal.compiler.ast;
15
16
Lines 86-91 Link Here
86
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
87
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
87
				}
88
				}
88
			}
89
			}
90
			analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
89
		}
91
		}
90
92
91
		// analyse the anonymous nested type
93
		// analyse the anonymous nested type
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-2 / +8 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
11
 *     							bug 185682 - Increment/decrement operators mark local variables as read
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.ast;
14
package org.eclipse.jdt.internal.compiler.ast;
13
15
Lines 963-969 Link Here
963
							&& methodScope.lastVisibleFieldID >= 0
965
							&& methodScope.lastVisibleFieldID >= 0
964
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
966
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
965
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
967
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
966
						scope.problemReporter().forwardReference(this, this.indexOfFirstFieldBinding-1, fieldBinding);
968
						if ((this.bits & IsMemberValueReference) != 0 && fieldBinding.id == methodScope.lastVisibleFieldID) {
969
							// false alarm, location is NOT a field initializer but the value in a memberValuePair
970
						} else {
971
							scope.problemReporter().forwardReference(this, this.indexOfFirstFieldBinding-1, fieldBinding);
972
						}
967
					}
973
					}
968
					if (isFieldUseDeprecated(fieldBinding, scope, this.indexOfFirstFieldBinding == this.tokens.length ? this.bits : 0)) {
974
					if (isFieldUseDeprecated(fieldBinding, scope, this.indexOfFirstFieldBinding == this.tokens.length ? this.bits : 0)) {
969
						scope.problemReporter().deprecatedField(fieldBinding, this);	
975
						scope.problemReporter().deprecatedField(fieldBinding, this);	
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (-1 / +21 lines)
Lines 7-16 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for 
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
13
 *     							bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
16
17
Lines 44-49 Link Here
44
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
45
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
45
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
46
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
46
		}
47
		}
48
		if (flowInfo.reachMode() == FlowInfo.REACHABLE)
49
			checkAgainstNullAnnotation(currentScope, this.expression.nullStatus(flowInfo));
47
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression);
50
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression);
48
		if (trackingVariable != null) {
51
		if (trackingVariable != null) {
49
			if (methodScope != trackingVariable.methodScope)
52
			if (methodScope != trackingVariable.methodScope)
Lines 119-124 Link Here
119
	currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
122
	currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
120
	return FlowInfo.DEAD_END;
123
	return FlowInfo.DEAD_END;
121
}
124
}
125
void checkAgainstNullAnnotation(BlockScope scope, int nullStatus) {
126
	if (nullStatus != FlowInfo.NON_NULL) {
127
		// if we can't prove non-null check against declared null-ness of the enclosing method:
128
		long tagBits;
129
		MethodBinding methodBinding;
130
		try {
131
			methodBinding = scope.methodScope().referenceMethod().binding;
132
			tagBits = methodBinding.tagBits;
133
		} catch (NullPointerException npe) {
134
			return;
135
		}
136
		if ((tagBits & TagBits.AnnotationNonNull) != 0) {
137
			char[][] annotationName = scope.environment().getNonNullAnnotationName();
138
			scope.problemReporter().nullityMismatch(this.expression, methodBinding.returnType, nullStatus, annotationName);
139
		}
140
	}
141
}
122
142
123
/**
143
/**
124
 * Retrun statement code generation
144
 * Retrun statement code generation
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java (-3 / +31 lines)
Lines 7-15 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for 
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 335093 - [compiler][null] minimal hook for future null annotation support
11
 *     							bug 335093 - [compiler][null] minimal hook for future null annotation support
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.ast;
15
package org.eclipse.jdt.internal.compiler.ast;
15
16
Lines 57-64 Link Here
57
	public static final int COMPLAINED_FAKE_REACHABLE = 1;
58
	public static final int COMPLAINED_FAKE_REACHABLE = 1;
58
	public static final int COMPLAINED_UNREACHABLE = 2;
59
	public static final int COMPLAINED_UNREACHABLE = 2;
59
	
60
	
60
/** Empty hook for checking null status against declaration using null annotations, once this will be supported. */
61
61
protected int checkAgainstNullAnnotation(BlockScope currentScope, LocalVariableBinding local, int nullStatus) {
62
/** Analysing arguments of MessageSend, ExplicitConstructorCall, AllocationExpression. */
63
protected void analyseArguments(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, MethodBinding methodBinding, Expression[] arguments)
64
{
65
	// compare actual null-status against parameter annotations of the called method:
66
	if (arguments != null && methodBinding.parameterNonNullness != null) {
67
		for (int i = 0; i < arguments.length; i++) {
68
			if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) {
69
				TypeBinding expectedType = methodBinding.parameters[i];
70
				Expression argument = arguments[i];
71
				int nullStatus = argument.nullStatus(flowInfo); // slight loss of precision: should also use the null info from the receiver.
72
				if (nullStatus != FlowInfo.NON_NULL) // if required non-null is not provided
73
					flowContext.recordNullityMismatch(currentScope, argument, nullStatus, expectedType);
74
			}
75
		}
76
	}
77
}
78
79
/** Check null-ness of 'local' against a possible null annotation */
80
protected int checkAssignmentAgainstNullAnnotation(BlockScope currentScope, FlowContext flowContext,
81
												   LocalVariableBinding local, int nullStatus, Expression expression)
82
{
83
	if (   local != null
84
		&& (local.tagBits & TagBits.AnnotationNonNull) != 0 
85
		&& nullStatus != FlowInfo.NON_NULL)
86
	{
87
		flowContext.recordNullityMismatch(currentScope, expression, nullStatus, local.type);
88
		nullStatus=FlowInfo.NON_NULL;
89
	}
62
	return nullStatus;
90
	return nullStatus;
63
}
91
}
64
92
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java (-2 / +26 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.flow;
12
package org.eclipse.jdt.internal.compiler.flow;
12
13
Lines 17-22 Link Here
17
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.Scope;
20
import org.eclipse.jdt.internal.compiler.lookup.Scope;
21
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
22
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
21
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
22
24
Lines 83-90 Link Here
83
	// check inconsistent null checks
85
	// check inconsistent null checks
84
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
86
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
85
		for (int i = 0; i < this.nullCount; i++) {
87
		for (int i = 0; i < this.nullCount; i++) {
86
			this.parent.recordUsingNullReference(scope, this.nullLocals[i],
88
			if (this.nullCheckTypes[i] == ASSIGN_TO_NONNULL)
87
					this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
89
				this.parent.recordNullityMismatch(scope, this.nullReferences[i],
90
						flowInfo.nullStatus(this.nullLocals[i]), this.expectedTypes[i]);
91
			else
92
				this.parent.recordUsingNullReference(scope, this.nullLocals[i],
93
						this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
94
88
		}
95
		}
89
	}
96
	}
90
	else { // no enclosing loop, be as precise as possible right now
97
	else { // no enclosing loop, be as precise as possible right now
Lines 165-170 Link Here
165
					}
172
					}
166
					if (flowInfo.isPotentiallyNull(local)) {
173
					if (flowInfo.isPotentiallyNull(local)) {
167
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
174
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
175
					}
176
					break;
177
				case ASSIGN_TO_NONNULL:
178
					int nullStatus = flowInfo.nullStatus(local);
179
					if (nullStatus != FlowInfo.NON_NULL) {
180
						char[][] annotationName = scope.environment().getNonNullAnnotationName();
181
						scope.problemReporter().nullityMismatch(expression, this.expectedTypes[i], nullStatus, annotationName);
168
					}
182
					}
169
					break;
183
					break;
170
				default:
184
				default:
Lines 442-445 Link Here
442
	this.nullReferences[this.nullCount] = expression;
456
	this.nullReferences[this.nullCount] = expression;
443
	this.nullCheckTypes[this.nullCount++] = status;
457
	this.nullCheckTypes[this.nullCount++] = status;
444
}
458
}
459
protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
460
	// cf. decision structure inside FinallyFlowContext.recordUsingNullReference(..)
461
	if (nullStatus == FlowInfo.UNKNOWN ||
462
			((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0 && nullStatus != FlowInfo.NULL)) {
463
		recordExpectedType(expectedType, this.nullCount);
464
		recordNullReference(expression.localVariableBinding(), expression, checkType);
465
		return true;
466
	}
467
	return false;
468
}
445
}
469
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-2 / +52 lines)
Lines 4-13 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.flow;
14
package org.eclipse.jdt.internal.compiler.flow;
13
15
Lines 52-57 Link Here
52
		// any null related operation happening within the try block
54
		// any null related operation happening within the try block
53
55
54
	public int tagBits;
56
	public int tagBits;
57
58
	// array to store the expected type from the potential error location (for display in error messages):
59
	public TypeBinding[] expectedTypes = null;
60
55
	public static final int DEFER_NULL_DIAGNOSTIC = 0x1;
61
	public static final int DEFER_NULL_DIAGNOSTIC = 0x1;
56
	public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2;
62
	public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2;
57
	/**
63
	/**
Lines 66-71 Link Here
66
public static final int CAN_ONLY_NON_NULL = 0x0002;
72
public static final int CAN_ONLY_NON_NULL = 0x0002;
67
//check against non null, with definite values -- comparisons
73
//check against non null, with definite values -- comparisons
68
public static final int MAY_NULL = 0x0003;
74
public static final int MAY_NULL = 0x0003;
75
//check binding a value to a @NonNull variable 
76
public final static int ASSIGN_TO_NONNULL = 0x0080;
69
// check against null, with potential values -- NPE guard
77
// check against null, with potential values -- NPE guard
70
public static final int CHECK_MASK = 0x00FF;
78
public static final int CHECK_MASK = 0x00FF;
71
public static final int IN_COMPARISON_NULL = 0x0100;
79
public static final int IN_COMPARISON_NULL = 0x0100;
Lines 548-553 Link Here
548
	// default implementation: do nothing
556
	// default implementation: do nothing
549
}
557
}
550
558
559
protected void recordExpectedType(TypeBinding expectedType, int nullCount) {
560
	if (nullCount == 0) {
561
		this.expectedTypes = new TypeBinding[5];
562
	} else if (this.expectedTypes == null) {
563
		int size = 5;
564
		while (size <= nullCount) size *= 2;
565
		this.expectedTypes = new TypeBinding[size];
566
	}
567
	else if (nullCount == this.expectedTypes.length) {
568
		System.arraycopy(this.expectedTypes, 0,
569
			this.expectedTypes = new TypeBinding[nullCount * 2], 0, nullCount);
570
	}
571
	this.expectedTypes[nullCount] = expectedType;
572
}
573
551
protected boolean recordFinalAssignment(VariableBinding variable, Reference finalReference) {
574
protected boolean recordFinalAssignment(VariableBinding variable, Reference finalReference) {
552
	return true; // keep going
575
	return true; // keep going
553
}
576
}
Lines 746-749 Link Here
746
	buffer.append(individualToString()).append('\n');
769
	buffer.append(individualToString()).append('\n');
747
	return buffer.toString();
770
	return buffer.toString();
748
}
771
}
772
773
/**
774
 * Record that a nullity mismatch was detected against an annotated type reference.
775
 * @param currentScope scope for error reporting
776
 * @param expression the expression violating the specification
777
 * @param nullStatus the null status of expression at the current location
778
 * @param expectedType the declared type of the spec'ed variable, for error reporting.
779
 */
780
public void recordNullityMismatch(BlockScope currentScope, Expression expression, int nullStatus, TypeBinding expectedType) {
781
	if (expression.localVariableBinding() != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields)
782
		// find the inner-most flowContext that might need deferred handling:
783
		FlowContext currentContext = this;
784
		while (currentContext != null) {
785
			// some flow contexts implement deferred checking, should we participate in that?
786
			if (currentContext.internalRecordNullityMismatch(expression, nullStatus, expectedType, ASSIGN_TO_NONNULL))
787
				return;
788
			currentContext = currentContext.parent;
789
		}
790
	}
791
	// no reason to defer, so report now:
792
	char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
793
	currentScope.problemReporter().nullityMismatch(expression, expectedType, nullStatus, annotationName);
794
}
795
protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
796
	// nop, to be overridden in subclasses
797
	return false; // not recorded
798
}
749
}
799
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-1 / +21 lines)
Lines 7-17 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - contribution for Bug 336428 - [compiler][null] bogus warning "redundant null check" in condition of do {} while() loop
10
 *     Stephan Herrmann - contributions for
11
 *     							bug 336428 - [compiler][null] bogus warning "redundant null check" in condition of do {} while() loop
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.flow;
14
package org.eclipse.jdt.internal.compiler.flow;
13
15
14
import java.util.ArrayList;
16
import java.util.ArrayList;
17
15
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
18
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
19
import org.eclipse.jdt.internal.compiler.ast.Expression;
17
import org.eclipse.jdt.internal.compiler.ast.Reference;
20
import org.eclipse.jdt.internal.compiler.ast.Reference;
Lines 21-26 Link Here
21
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.Scope;
26
import org.eclipse.jdt.internal.compiler.lookup.Scope;
27
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
28
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
25
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
26
30
Lines 246-251 Link Here
246
						continue;
250
						continue;
247
					}
251
					}
248
					break;
252
					break;
253
				case ASSIGN_TO_NONNULL:
254
					this.parent.recordNullityMismatch(scope, expression, flowInfo.nullStatus(local), this.expectedTypes[i]);
255
					break;
249
				default:
256
				default:
250
					// never happens
257
					// never happens
251
			}
258
			}
Lines 337-342 Link Here
337
						this.nullReferences[i] = null;
344
						this.nullReferences[i] = null;
338
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
345
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
339
						continue;
346
						continue;
347
					}
348
					break;
349
				case ASSIGN_TO_NONNULL:
350
					int nullStatus = flowInfo.nullStatus(local);
351
					if (nullStatus != FlowInfo.NON_NULL) {
352
						char[][] annotationName = scope.environment().getNonNullAnnotationName();
353
						scope.problemReporter().nullityMismatch(expression, this.expectedTypes[i], nullStatus, annotationName);
340
					}
354
					}
341
					break;
355
					break;
342
				default:
356
				default:
Lines 667-670 Link Here
667
	public boolean hasEscapingExceptions() {
681
	public boolean hasEscapingExceptions() {
668
		return this.escapingExceptionCatchSites != null;
682
		return this.escapingExceptionCatchSites != null;
669
	}
683
	}
684
685
	protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
686
		recordExpectedType(expectedType, this.nullCount);
687
		recordNullReference(expression.localVariableBinding(), expression, checkType);
688
		return true;
689
	}
670
}
690
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java (-4 / +95 lines)
Lines 12-17 Link Here
12
 *     							bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
12
 *     							bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
13
 *     							bug 295551 - Add option to automatically promote all warnings to errors
13
 *     							bug 295551 - Add option to automatically promote all warnings to errors
14
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
15
 *								bug 186342 - [compiler][null] Using annotations for null checking
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.impl;
17
package org.eclipse.jdt.internal.compiler.impl;
17
18
Lines 26-31 Link Here
26
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
27
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
29
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
30
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
29
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
31
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
30
import org.eclipse.jdt.internal.compiler.util.Util;
32
import org.eclipse.jdt.internal.compiler.util.Util;
31
33
Lines 142-147 Link Here
142
	public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$
144
	public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$
143
	public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
145
	public static final String OPTION_ReportPotentiallyUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"; //$NON-NLS-1$
144
	public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
146
	public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
147
	public static final String OPTION_ReportNullSpecViolation = "org.eclipse.jdt.core.compiler.problem.nullSpecViolation";  //$NON-NLS-1$
148
	public static final String OPTION_ReportPotentialNullSpecViolation = "org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation";  //$NON-NLS-1$
149
	public static final String OPTION_ReportNullSpecInsufficientInfo = "org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo";  //$NON-NLS-1$
150
	public static final String OPTION_ReportRedundantNullAnnotation = "org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation";  //$NON-NLS-1$
151
	public static final String OPTION_AnnotationBasedNullAnalysis = "org.eclipse.jdt.core.compiler.annotation.nullanalysis"; //$NON-NLS-1$
152
	public static final String OPTION_NullableAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nullable"; //$NON-NLS-1$
153
	public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$
154
	public static final String OPTION_NonNullByDefaultAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnullbydefault"; //$NON-NLS-1$
155
	// defaults for the above:
156
	static final char[][] DEFAULT_NULLABLE_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.Nullable".toCharArray()); //$NON-NLS-1$
157
	static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$
158
	static final char[][] DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNullByDefault".toCharArray()); //$NON-NLS-1$
159
	public static final String OPTION_NonNullIsDefault = "org.eclipse.jdt.core.compiler.annotation.nonnullisdefault";  //$NON-NLS-1$
145
	/**
160
	/**
146
	 * Possible values for configurable options
161
	 * Possible values for configurable options
147
	 */
162
	 */
Lines 245-254 Link Here
245
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
260
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
246
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
261
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
247
	public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7;
262
	public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7;
248
	// bits 8-10 reserved for https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342
263
	public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit8;
249
	public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit11;
264
	public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit9;
250
	public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit12;
265
	public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit10;
251
	public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit13;
266
	public static final int NullSpecViolation = IrritantSet.GROUP2 | ASTNode.Bit11;
267
	public static final int PotentialNullSpecViolation = IrritantSet.GROUP2 | ASTNode.Bit12;
268
	public static final int NullSpecInsufficientInfo = IrritantSet.GROUP2 | ASTNode.Bit13;
269
	public static final int RedundantNullAnnotation = IrritantSet.GROUP2 | ASTNode.Bit14;
252
270
253
	// Severity level for handlers
271
	// Severity level for handlers
254
	/** 
272
	/** 
Lines 370-375 Link Here
370
	public boolean includeNullInfoFromAsserts;
388
	public boolean includeNullInfoFromAsserts;
371
	/** Controls whether forced generic type problems get reported  */
389
	/** Controls whether forced generic type problems get reported  */
372
	public boolean reportUnavoidableGenericTypeProblems;
390
	public boolean reportUnavoidableGenericTypeProblems;
391
392
	// === Support for Null Annotations: ===
393
	/** Master switch for null analysis based on annotations: */
394
	public boolean isAnnotationBasedNullAnalysisEnabled;
395
	/** Fully qualified name of annotation to use as marker for nullable types. */
396
	public char[][] nullableAnnotationName;
397
	/** Fully qualified name of annotation to use as marker for nonnull types. */
398
	public char[][] nonNullAnnotationName;
399
	/** Fully qualified name of annotation to use as marker for default nonnull. */
400
	public char[][] nonNullByDefaultAnnotationName;
401
	/** TagBits-encoded default for non-annotated types. */
402
	public long defaultNonNullness; // 0 or TagBits#AnnotationNonNull
373
403
374
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
404
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
375
	public final static String[] warningTokens = {
405
	public final static String[] warningTokens = {
Lines 567-572 Link Here
567
				return OPTION_ReportPotentiallyUnclosedCloseable;
597
				return OPTION_ReportPotentiallyUnclosedCloseable;
568
			case ExplicitlyClosedAutoCloseable :
598
			case ExplicitlyClosedAutoCloseable :
569
				return OPTION_ReportExplicitlyClosedAutoCloseable;
599
				return OPTION_ReportExplicitlyClosedAutoCloseable;
600
			case NullSpecViolation :
601
				return OPTION_ReportNullSpecViolation;
602
			case PotentialNullSpecViolation :
603
				return OPTION_ReportPotentialNullSpecViolation;
604
			case NullSpecInsufficientInfo :
605
				return OPTION_ReportNullSpecInsufficientInfo;
606
			case RedundantNullAnnotation :
607
				return OPTION_ReportRedundantNullAnnotation;
570
		}
608
		}
571
		return null;
609
		return null;
572
	}
610
	}
Lines 733-738 Link Here
733
			OPTION_ReportUnclosedCloseable,
771
			OPTION_ReportUnclosedCloseable,
734
			OPTION_ReportPotentiallyUnclosedCloseable,
772
			OPTION_ReportPotentiallyUnclosedCloseable,
735
			OPTION_ReportExplicitlyClosedAutoCloseable,
773
			OPTION_ReportExplicitlyClosedAutoCloseable,
774
			OPTION_AnnotationBasedNullAnalysis,
775
			OPTION_NonNullAnnotationName,
776
			OPTION_NullableAnnotationName,
777
			OPTION_NonNullByDefaultAnnotationName,
778
			OPTION_NonNullIsDefault,
779
			OPTION_ReportNullSpecViolation,
780
			OPTION_ReportPotentialNullSpecViolation,
781
			OPTION_ReportRedundantNullAnnotation
736
		};
782
		};
737
		return result;
783
		return result;
738
	}
784
	}
Lines 795-800 Link Here
795
			case NullReference :
841
			case NullReference :
796
			case PotentialNullReference :
842
			case PotentialNullReference :
797
			case RedundantNullCheck :
843
			case RedundantNullCheck :
844
			case NullSpecViolation :
845
			case PotentialNullSpecViolation :
846
			case NullSpecInsufficientInfo :
847
			case RedundantNullAnnotation :
798
				return "null"; //$NON-NLS-1$
848
				return "null"; //$NON-NLS-1$
799
			case FallthroughCase :
849
			case FallthroughCase :
800
				return "fallthrough"; //$NON-NLS-1$
850
				return "fallthrough"; //$NON-NLS-1$
Lines 1008-1013 Link Here
1008
		optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
1058
		optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
1009
		optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
1059
		optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
1010
		optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
1060
		optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
1061
		optionsMap.put(OPTION_AnnotationBasedNullAnalysis, this.isAnnotationBasedNullAnalysisEnabled ? ENABLED : DISABLED);
1062
		optionsMap.put(OPTION_ReportNullSpecViolation, getSeverityString(NullSpecViolation));
1063
		optionsMap.put(OPTION_ReportPotentialNullSpecViolation, getSeverityString(PotentialNullSpecViolation));
1064
		optionsMap.put(OPTION_ReportNullSpecInsufficientInfo, getSeverityString(NullSpecInsufficientInfo));
1065
		optionsMap.put(OPTION_ReportRedundantNullAnnotation, getSeverityString(RedundantNullAnnotation));
1066
		optionsMap.put(OPTION_NullableAnnotationName, String.valueOf(CharOperation.concatWith(this.nullableAnnotationName, '.')));
1067
		optionsMap.put(OPTION_NonNullAnnotationName, String.valueOf(CharOperation.concatWith(this.nonNullAnnotationName, '.')));
1068
		optionsMap.put(OPTION_NonNullByDefaultAnnotationName, String.valueOf(CharOperation.concatWith(this.nonNullByDefaultAnnotationName, '.')));
1069
		if (this.defaultNonNullness == TagBits.AnnotationNonNull)
1070
			optionsMap.put(OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1071
		else
1072
			optionsMap.put(OPTION_NonNullIsDefault, CompilerOptions.DISABLED);
1011
		return optionsMap;
1073
		return optionsMap;
1012
	}
1074
	}
1013
1075
Lines 1158-1163 Link Here
1158
		
1220
		
1159
		// allow null info from asserts to be considered downstream by default
1221
		// allow null info from asserts to be considered downstream by default
1160
		this.includeNullInfoFromAsserts = false;
1222
		this.includeNullInfoFromAsserts = false;
1223
		
1224
		this.isAnnotationBasedNullAnalysisEnabled = false;
1225
		this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
1226
		this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
1227
		this.nonNullByDefaultAnnotationName = DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME;
1161
	}
1228
	}
1162
1229
1163
	public void set(Map optionsMap) {
1230
	public void set(Map optionsMap) {
Lines 1441-1446 Link Here
1441
		if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
1508
		if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
1442
		if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
1509
		if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
1443
		if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
1510
		if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
1511
		if ((optionValue = optionsMap.get(OPTION_AnnotationBasedNullAnalysis)) != null) {
1512
			this.isAnnotationBasedNullAnalysisEnabled = ENABLED.equals(optionValue);
1513
		}
1514
		if (this.isAnnotationBasedNullAnalysisEnabled) {
1515
			if ((optionValue = optionsMap.get(OPTION_ReportNullSpecViolation)) != null) updateSeverity(NullSpecViolation, optionValue);
1516
			if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullSpecViolation)) != null) updateSeverity(PotentialNullSpecViolation, optionValue);
1517
			if ((optionValue = optionsMap.get(OPTION_ReportNullSpecInsufficientInfo)) != null) updateSeverity(NullSpecInsufficientInfo, optionValue);
1518
			if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullAnnotation)) != null) updateSeverity(RedundantNullAnnotation, optionValue);
1519
			if ((optionValue = optionsMap.get(OPTION_NullableAnnotationName)) != null) {
1520
				this.nullableAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1521
			}
1522
			if ((optionValue = optionsMap.get(OPTION_NonNullAnnotationName)) != null) {
1523
				this.nonNullAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1524
			}
1525
			if ((optionValue = optionsMap.get(OPTION_NonNullByDefaultAnnotationName)) != null) {
1526
				this.nonNullByDefaultAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1527
			}
1528
			if ((optionValue = optionsMap.get(OPTION_NonNullIsDefault)) != null) {
1529
				if (CompilerOptions.ENABLED.equals(optionValue))
1530
					this.defaultNonNullness = TagBits.AnnotationNonNull;
1531
				else if (CompilerOptions.DISABLED.equals(optionValue))
1532
					this.defaultNonNullness = 0;
1533
			}
1534
		}
1444
1535
1445
		// Javadoc options
1536
		// Javadoc options
1446
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
1537
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java (-4 / +17 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
14
13
package org.eclipse.jdt.internal.compiler.impl;
15
package org.eclipse.jdt.internal.compiler.impl;
Lines 102-109 Link Here
102
			.set(
104
			.set(
103
				CompilerOptions.DeadCode
105
				CompilerOptions.DeadCode
104
				|CompilerOptions.Tasks
106
				|CompilerOptions.Tasks
105
				|CompilerOptions.UnclosedCloseable);
107
				|CompilerOptions.UnclosedCloseable
106
			
108
				|CompilerOptions.NullSpecInsufficientInfo
109
				|CompilerOptions.RedundantNullAnnotation);
110
		// default errors IF AnnotationBasedNullAnalysis is enabled:
111
		COMPILER_DEFAULT_ERRORS.set(
112
				CompilerOptions.NullSpecViolation
113
				|CompilerOptions.PotentialNullSpecViolation);
114
107
		ALL.setAll();
115
		ALL.setAll();
108
		HIDING
116
		HIDING
109
			.set(CompilerOptions.FieldHiding)
117
			.set(CompilerOptions.FieldHiding)
Lines 111-117 Link Here
111
			.set(CompilerOptions.TypeHiding);
119
			.set(CompilerOptions.TypeHiding);
112
		NULL
120
		NULL
113
			.set(CompilerOptions.PotentialNullReference)
121
			.set(CompilerOptions.PotentialNullReference)
114
			.set(CompilerOptions.RedundantNullCheck);
122
			.set(CompilerOptions.RedundantNullCheck)
123
			.set(CompilerOptions.NullSpecViolation)
124
			.set(CompilerOptions.PotentialNullSpecViolation)
125
			.set(CompilerOptions.NullSpecInsufficientInfo)
126
			.set(CompilerOptions.RedundantNullAnnotation);
127
115
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
128
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
116
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
129
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
117
		UNUSED
130
		UNUSED
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-1 / +100 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
14
package org.eclipse.jdt.internal.compiler.lookup;
13
15
Lines 16-24 Link Here
16
import org.eclipse.jdt.core.compiler.CharOperation;
18
import org.eclipse.jdt.core.compiler.CharOperation;
17
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.env.*;
20
import org.eclipse.jdt.internal.compiler.env.*;
21
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
19
import org.eclipse.jdt.internal.compiler.impl.Constant;
22
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
23
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
21
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
24
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
25
import org.eclipse.jdt.internal.compiler.util.Util;
22
26
23
/*
27
/*
24
Not all fields defined by this type are initialized when it is created.
28
Not all fields defined by this type are initialized when it is created.
Lines 383-388 Link Here
383
		}
387
		}
384
		if (this.environment.globalOptions.storeAnnotations)
388
		if (this.environment.globalOptions.storeAnnotations)
385
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
389
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
390
391
		scanTypeForNullAnnotation(binaryType);
386
	} finally {
392
	} finally {
387
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
393
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
388
		if (this.fields == null)
394
		if (this.fields == null)
Lines 589-594 Link Here
589
	// fixup the declaring element of the type variable
595
	// fixup the declaring element of the type variable
590
	for (int i = 0, length = typeVars.length; i < length; i++)
596
	for (int i = 0, length = typeVars.length; i < length; i++)
591
		typeVars[i].declaringElement = result;
597
		typeVars[i].declaringElement = result;
598
599
	scanMethodForNullAnnotation(method, result);
600
592
	return result;
601
	return result;
593
}
602
}
594
603
Lines 1142-1147 Link Here
1142
	}
1151
	}
1143
	return this.storedAnnotations;
1152
	return this.storedAnnotations;
1144
}
1153
}
1154
void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) {
1155
	char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
1156
	char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
1157
	if (nullableAnnotationName == null || nonNullAnnotationName == null)
1158
		return; // not configured to use null annotations
1159
1160
	// return:
1161
	IBinaryAnnotation[] annotations = method.getAnnotations();
1162
	if (annotations != null) {
1163
		for (int i = 0; i < annotations.length; i++) {
1164
			char[] annotationTypeName = annotations[i].getTypeName();
1165
			if (annotationTypeName[0] != Util.C_RESOLVED)
1166
				continue;
1167
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1168
			if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1169
				methodBinding.tagBits |= TagBits.AnnotationNonNull;
1170
				break;
1171
			}
1172
			if (CharOperation.equals(typeName, nullableAnnotationName)) {
1173
				methodBinding.tagBits |= TagBits.AnnotationNullable;
1174
				break;
1175
			}
1176
		}
1177
	}
1178
1179
	// parameters:
1180
	TypeBinding[] parameters = methodBinding.parameters;
1181
	for (int j = 0; j < parameters.length; j++) {
1182
		IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j);
1183
		if (paramAnnotations != null) {
1184
			for (int i = 0; i < paramAnnotations.length; i++) {
1185
				char[] annotationTypeName = paramAnnotations[i].getTypeName();
1186
				if (annotationTypeName[0] != Util.C_RESOLVED)
1187
					continue;
1188
				char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1189
				if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1190
					if (methodBinding.parameterNonNullness == null)
1191
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1192
					methodBinding.parameterNonNullness[j] = Boolean.TRUE;
1193
					break;
1194
				} else if (CharOperation.equals(typeName, nullableAnnotationName)) {
1195
					if (methodBinding.parameterNonNullness == null)
1196
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1197
					methodBinding.parameterNonNullness[j] = Boolean.FALSE;
1198
					break;
1199
				}
1200
			}
1201
		}
1202
	}
1203
}
1204
void scanTypeForNullAnnotation(IBinaryType binaryType) {
1205
	char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
1206
	if (nonNullByDefaultAnnotationName == null)
1207
		return; // not configured to use null annotations
1208
1209
	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
1210
	if (annotations != null) {
1211
		long annotationBit = 0L;
1212
		TypeBinding defaultNullness = null;
1213
		for (int i = 0; i < annotations.length; i++) {
1214
			char[] annotationTypeName = annotations[i].getTypeName();
1215
			if (annotationTypeName[0] != Util.C_RESOLVED)
1216
				continue;
1217
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1218
			if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
1219
				IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
1220
				if (elementValuePairs != null && elementValuePairs.length == 1) {
1221
					Object value = elementValuePairs[0].getValue();
1222
					if (value instanceof BooleanConstant
1223
						&& !((BooleanConstant)value).booleanValue())
1224
					{
1225
						// parameter is 'false': this means we cancel defaults from outer scopes:
1226
						annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
1227
						defaultNullness = ReferenceBinding.NULL_UNSPECIFIED;
1228
						break;
1229
					}
1230
				}
1231
				annotationBit = TagBits.AnnotationNonNullByDefault;
1232
				defaultNullness = this.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, false/*resolve*/);
1233
				break;
1234
			}
1235
		}
1236
		if (annotationBit != 0L) {
1237
			this.tagBits |= annotationBit;
1238
			if (CharOperation.equals(this.sourceName(), TypeConstants.PACKAGE_INFO_NAME))
1239
				this.getPackage().nullnessDefaultAnnotation = defaultNullness;
1240
		}
1241
	}
1242
}
1243
1145
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1244
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1146
*
1245
*
1147
* NOTE: superclass of a binary type is resolved when needed
1246
* NOTE: superclass of a binary type is resolved when needed
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java (-6 / +9 lines)
Lines 4-15 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
11
 *     							bug 185682 - Increment/decrement operators mark local variables as read
11
 *     							bug 185682 - Increment/decrement operators mark local variables as read
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 158-164 Link Here
158
					annotations = new AnnotationBinding[length];
159
					annotations = new AnnotationBinding[length];
159
					for (int i = 0; i < length; i++)
160
					for (int i = 0; i < length; i++)
160
						annotations[i] = new AnnotationBinding(annotationNodes[i]);
161
						annotations[i] = new AnnotationBinding(annotationNodes[i]);
161
					setAnnotations(annotations);
162
					setAnnotations(annotations, this.declaringScope);
162
				}
163
				}
163
			}
164
			}
164
		}
165
		}
Lines 212-221 Link Here
212
		this.initializationCount++;
213
		this.initializationCount++;
213
	}
214
	}
214
215
215
	public void setAnnotations(AnnotationBinding[] annotations) {
216
	public void setAnnotations(AnnotationBinding[] annotations, Scope scope) {
216
		if (this.declaringScope == null) return;
217
		// note: we don's use this.declaringScope because we might be called before Scope.addLocalVariable(this)
217
218
		//       which is where this.declaringScope is set.
218
		SourceTypeBinding sourceType = this.declaringScope.enclosingSourceType();
219
		if (scope == null)
220
			return;
221
		SourceTypeBinding sourceType = scope.enclosingSourceType();
219
		if (sourceType != null)
222
		if (sourceType != null)
220
			sourceType.storeAnnotations(this, annotations);
223
			sourceType.storeAnnotations(this, annotations);
221
	}
224
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java (-1 / +76 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - contribution for bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
10
 *     Stephan Herrmann - contributions for
11
 *     							bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
14
package org.eclipse.jdt.internal.compiler.lookup;
13
15
Lines 76-81 Link Here
76
	public boolean isProcessingAnnotations = false;
78
	public boolean isProcessingAnnotations = false;
77
	public boolean mayTolerateMissingType = false;
79
	public boolean mayTolerateMissingType = false;
78
80
81
	PackageBinding nullableAnnotationPackage;			// the package supposed to contain the Nullable annotation type
82
	PackageBinding nonnullAnnotationPackage;			// the package supposed to contain the NonNull annotation type
83
	PackageBinding nonnullByDefaultAnnotationPackage;	// the package supposed to contain the NonNullByDefault annotation type
84
79
	final static int BUILD_FIELDS_AND_METHODS = 4;
85
	final static int BUILD_FIELDS_AND_METHODS = 4;
80
	final static int BUILD_TYPE_HIERARCHY = 1;
86
	final static int BUILD_TYPE_HIERARCHY = 1;
81
	final static int CHECK_AND_SET_IMPORTS = 2;
87
	final static int CHECK_AND_SET_IMPORTS = 2;
Lines 83-88 Link Here
83
89
84
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
90
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
85
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
91
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
92
86
93
87
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
94
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
88
	this.typeRequestor = typeRequestor;
95
	this.typeRequestor = typeRequestor;
Lines 1073-1078 Link Here
1073
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1080
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1074
}
1081
}
1075
1082
1083
public char[][] getNullableAnnotationName() {
1084
	return this.globalOptions.nullableAnnotationName;
1085
}
1086
1087
public char[][] getNonNullAnnotationName() {
1088
	return this.globalOptions.nonNullAnnotationName;
1089
}
1090
1091
public char[][] getNonNullByDefaultAnnotationName() {
1092
	return this.globalOptions.nonNullByDefaultAnnotationName;
1093
}
1094
1095
/**
1096
 * Answer the type binding representing the null-annotation identified by the given tag bits.
1097
 * @param annotationTagBit tag bits potentially denoting a null-annotation
1098
 * @param resolve should the resulting type binding be resolved?
1099
 * @return the corresponding annotation type binding
1100
 * 		or <code>null</code> if no annotation bits are contained in the given tag bits.
1101
 */
1102
public TypeBinding getNullAnnotationBinding(long annotationTagBit, boolean resolve) {
1103
	char[][] name = null;
1104
	if (annotationTagBit == TagBits.AnnotationNonNull)
1105
		name = getNonNullAnnotationName();
1106
	else if (annotationTagBit == TagBits.AnnotationNullable)
1107
		name = getNullableAnnotationName();
1108
	else
1109
		return null;
1110
	if (resolve)
1111
		return getType(name);
1112
	else
1113
		return getTypeFromCompoundName(name, false, false);
1114
}
1115
1116
/**
1117
 * Inspect the given tag bits and answer a corresponding null annotation type binding
1118
 * @param defaultTagBit tag bits representing the default applicable at the current code location
1119
 * @param resolve should the resulting type binding be resolved?
1120
 * @return the corresponding concrete annotation type binding (<code>@NonNull</code> or <code>@Nullable</code>)
1121
 * 		or <code>null</code> if no bits of a default-annotation are contained in the given tag bits.
1122
 */
1123
public TypeBinding getNullAnnotationBindingFromDefault(long defaultTagBit, boolean resolve) {
1124
	if ((defaultTagBit & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
1125
		return ReferenceBinding.NULL_UNSPECIFIED;
1126
	if ((defaultTagBit & TagBits.AnnotationNonNullByDefault) != 0)
1127
		return getNullAnnotationBinding(TagBits.AnnotationNonNull, resolve);
1128
	return null;
1129
}
1130
1131
TypeBinding getNullAnnotationResolved(TypeBinding nullAnnotation, Scope scope) {
1132
	// avoid unspecific error "The type in.valid cannot be resolved. It is indirectly referenced from required .class files"
1133
	boolean tolerateMissing = this.mayTolerateMissingType;
1134
	this.mayTolerateMissingType = true;
1135
	try {
1136
		int id = nullAnnotation.id;
1137
		nullAnnotation = BinaryTypeBinding.resolveType(nullAnnotation, this, false);
1138
		nullAnnotation.id = id;
1139
	} finally {
1140
		this.mayTolerateMissingType = tolerateMissing;
1141
	}
1142
	if (nullAnnotation instanceof MissingTypeBinding) {
1143
		// convert error into a specific one:
1144
		scope.problemReporter().missingNullAnnotationType(((MissingTypeBinding)nullAnnotation).compoundName);
1145
		return null;
1146
	}
1147
	return nullAnnotation;
1148
}
1149
1076
/* Answer the top level package named name if it exists in the cache.
1150
/* Answer the top level package named name if it exists in the cache.
1077
* Answer theNotFoundPackage if it could not be resolved the first time
1151
* Answer theNotFoundPackage if it could not be resolved the first time
1078
* it was looked up, otherwise answer null.
1152
* it was looked up, otherwise answer null.
Lines 1454-1459 Link Here
1454
	this.unitBeingCompleted = null; // in case AbortException occurred
1528
	this.unitBeingCompleted = null; // in case AbortException occurred
1455
1529
1456
	this.classFilePool.reset();
1530
	this.classFilePool.reset();
1531
1457
	// name environment has a longer life cycle, and must be reset in
1532
	// name environment has a longer life cycle, and must be reset in
1458
	// the code which created it.
1533
	// the code which created it.
1459
}
1534
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java (-1 / +40 lines)
Lines 4-12 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 33-38 Link Here
33
	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
34
	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
34
	char[] signature;
35
	char[] signature;
35
	public long tagBits;
36
	public long tagBits;
37
38
	/** Store nullness information from annotation (incl. applicable default). */
39
	public Boolean[] parameterNonNullness;  // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
36
40
37
protected MethodBinding() {
41
protected MethodBinding() {
38
	// for creating problem or synthetic method
42
	// for creating problem or synthetic method
Lines 439-444 Link Here
439
	return this.selector;
443
	return this.selector;
440
}
444
}
441
445
446
/**
447
 * After method verifier has finished, fill in missing nullness values from the applicable default.
448
 * @param annotationBinding the null annotation specified to be the default at the current code location.
449
 */
450
protected void fillInDefaultNonNullness(TypeBinding annotationBinding) {
451
	if (this.parameterNonNullness == null)
452
		this.parameterNonNullness = new Boolean[this.parameters.length];
453
	AbstractMethodDeclaration sourceMethod = sourceMethod();
454
	for (int i = 0; i < this.parameterNonNullness.length; i++) {
455
		if (this.parameters[i].isBaseType())
456
			continue;
457
		boolean added = false;
458
		if (this.parameterNonNullness[i] == null) {
459
			added = true;
460
			this.parameterNonNullness[i] = Boolean.TRUE;
461
			if (sourceMethod != null)
462
				sourceMethod.addParameterNonNullAnnotation(i, (ReferenceBinding)annotationBinding);
463
		} else if (this.parameterNonNullness[i].booleanValue()) {
464
			sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
465
		}
466
		if (added)
467
			this.tagBits |= TagBits.HasParameterAnnotations;
468
	}
469
	if (   this.returnType != null
470
		&& !this.returnType.isBaseType()
471
		&& (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
472
	{
473
		this.tagBits |= TagBits.AnnotationNonNull;
474
		if (sourceMethod != null)
475
			sourceMethod.addNullnessAnnotation((ReferenceBinding)annotationBinding);
476
	} else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
477
		sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
478
	}
479
}
480
442
public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) {
481
public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) {
443
	MethodBinding inheritedOriginal = inheritedMethod.original();
482
	MethodBinding inheritedOriginal = inheritedMethod.original();
444
	TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass);
483
	TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (-1 / +98 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 165-170 Link Here
165
				|| this.type.superclass.erasure().findSuperTypeOriginatingFrom(originalInherited.declaringClass) == null)
166
				|| this.type.superclass.erasure().findSuperTypeOriginatingFrom(originalInherited.declaringClass) == null)
166
					this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original());
167
					this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original());
167
		}
168
		}
169
		if (!concreteMethod.isStatic() && !abstractMethod.isStatic())
170
			checkNullSpecInheritance(concreteMethod, abstractMethod);
168
	}
171
	}
169
}
172
}
170
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) {
173
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) {
Lines 359-364 Link Here
359
	}
362
	}
360
363
361
	return false;
364
	return false;
365
}
366
void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods)
367
{
368
	super.checkAgainstInheritedMethods(currentMethod, methods, length, allInheritedMethods);
369
	for (int i = length; --i >= 0;)
370
		if (!currentMethod.isStatic() && !methods[i].isStatic())
371
			checkNullSpecInheritance(currentMethod, methods[i]);
372
}
373
374
void checkNullSpecInheritance(MethodBinding currentMethod, MethodBinding inheritedMethod) {
375
	long inheritedBits = inheritedMethod.tagBits;
376
	long currentBits = currentMethod.tagBits;
377
	AbstractMethodDeclaration srcMethod = null;
378
	if (this.type.equals(currentMethod.declaringClass)) // is currentMethod from the current type?
379
		srcMethod = currentMethod.sourceMethod();
380
381
	// return type:
382
	if ((inheritedBits & TagBits.AnnotationNonNull) != 0) {
383
		long currentNullBits = currentBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable);
384
		if (currentNullBits != TagBits.AnnotationNonNull) {
385
			if (srcMethod != null) {
386
				this.type.scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod,
387
															this.environment.getNonNullAnnotationName());
388
			} else {
389
				this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
390
				return;
391
			}
392
		}
393
	}
394
395
	// parameters:
396
	Argument[] currentArguments = srcMethod == null ? null : srcMethod.arguments;
397
	if (inheritedMethod.parameterNonNullness != null) {
398
		// inherited method has null-annotations, check compatibility:
399
400
		for (int i = 0; i < inheritedMethod.parameterNonNullness.length; i++) {
401
			Argument currentArgument = currentArguments == null ? null : currentArguments[i];
402
403
			Boolean inheritedNonNullNess = inheritedMethod.parameterNonNullness[i];
404
			Boolean currentNonNullNess = (currentMethod.parameterNonNullness == null)
405
										? null : currentMethod.parameterNonNullness[i];
406
			if (inheritedNonNullNess != null) {				// super has a null annotation
407
				if (currentNonNullNess == null) {			// current parameter lacks null annotation
408
					boolean needNonNull = false;
409
					char[][] annotationName;
410
					if (inheritedNonNullNess == Boolean.TRUE) {
411
						needNonNull = true;
412
						annotationName = this.environment.getNonNullAnnotationName();
413
					} else {
414
						annotationName = this.environment.getNullableAnnotationName();
415
					}
416
					if (currentArgument != null) {
417
						this.type.scope.problemReporter().parameterLackingNonNullAnnotation(
418
								currentArgument,
419
								inheritedMethod.declaringClass,
420
								needNonNull,
421
								annotationName);
422
						continue;
423
					} else {
424
						this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
425
						break;
426
					}
427
				}
428
			}
429
			if (inheritedNonNullNess != Boolean.TRUE) {		// super parameter is not restricted to @NonNull
430
				if (currentNonNullNess == Boolean.TRUE) { 	// current parameter is restricted to @NonNull
431
					if (currentArgument != null)
432
						this.type.scope.problemReporter().illegalRedefinitionToNonNullParameter(
433
														currentArgument,
434
														inheritedMethod.declaringClass,
435
														inheritedNonNullNess == null
436
														? null
437
														: this.environment.getNullableAnnotationName());
438
					else
439
						this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
440
				}
441
			}
442
		}
443
	} else if (currentMethod.parameterNonNullness != null) {
444
		// super method has no annotations but current has
445
		for (int i = 0; i < currentMethod.parameterNonNullness.length; i++) {
446
			if (currentMethod.parameterNonNullness[i] == Boolean.TRUE) { // tightening from unconstrained to @NonNull
447
				if (currentArguments != null) {
448
					this.type.scope.problemReporter().illegalRedefinitionToNonNullParameter(
449
																	currentArguments[i],
450
																	inheritedMethod.declaringClass,
451
																	null);
452
				} else {
453
					this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
454
					break;
455
				}
456
			}
457
		}
458
	}
362
}
459
}
363
460
364
void reportRawReferences() {
461
void reportRawReferences() {
Lines 935-941 Link Here
935
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
1032
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
936
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
1033
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
937
1034
938
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
1035
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
939
	if (currentMethod.returnType == inheritedMethod.returnType.erasure()) {
1036
	if (currentMethod.returnType == inheritedMethod.returnType.erasure()) {
940
		TypeBinding[] currentParams = currentMethod.parameters;
1037
		TypeBinding[] currentParams = currentMethod.parameters;
941
		TypeBinding[] inheritedParams = inheritedMethod.parameters;
1038
		TypeBinding[] inheritedParams = inheritedMethod.parameters;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java (-1 / +56 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 22-27 Link Here
22
	public LookupEnvironment environment;
23
	public LookupEnvironment environment;
23
	HashtableOfType knownTypes;
24
	HashtableOfType knownTypes;
24
	HashtableOfPackage knownPackages;
25
	HashtableOfPackage knownPackages;
26
27
	// annotation type binding representing the default that has been defined for this package (using @NonNullByDefault)
28
	protected TypeBinding nullnessDefaultAnnotation;
29
25
protected PackageBinding() {
30
protected PackageBinding() {
26
	// for creating problem package
31
	// for creating problem package
27
}
32
}
Lines 36-41 Link Here
36
	this.environment = environment;
41
	this.environment = environment;
37
	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
42
	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
38
	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
43
	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
44
	if (compoundName != CharOperation.NO_CHAR_CHAR)
45
		checkIfNullAnnotationPackage();
39
}
46
}
40
47
41
public PackageBinding(LookupEnvironment environment) {
48
public PackageBinding(LookupEnvironment environment) {
Lines 58-63 Link Here
58
	if (this.knownTypes == null)
65
	if (this.knownTypes == null)
59
		this.knownTypes = new HashtableOfType(25);
66
		this.knownTypes = new HashtableOfType(25);
60
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
67
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
68
	if (element.isAnnotationType() || element instanceof UnresolvedReferenceBinding) // unresolved types don't yet have the modifiers set
69
		checkIfNullAnnotationType(element);
61
}
70
}
62
71
63
void clearMissingTagBit() {
72
void clearMissingTagBit() {
Lines 230-235 Link Here
230
	return ProblemReasons.NoError;
239
	return ProblemReasons.NoError;
231
}
240
}
232
241
242
243
void checkIfNullAnnotationPackage() {
244
	LookupEnvironment env = this.environment;
245
	if (env.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
246
		if (isPackageOfQualifiedTypeName(this.compoundName, env.getNullableAnnotationName()))
247
			env.nullableAnnotationPackage = this;
248
		if (isPackageOfQualifiedTypeName(this.compoundName, env.getNonNullAnnotationName()))
249
			env.nonnullAnnotationPackage = this;
250
		if (isPackageOfQualifiedTypeName(this.compoundName, env.getNonNullByDefaultAnnotationName()))
251
			env.nonnullByDefaultAnnotationPackage = this;
252
	}
253
}
254
255
private boolean isPackageOfQualifiedTypeName(char[][] packageName, char[][] typeName) {
256
	if (typeName == null || typeName.length -1 != packageName.length)
257
		return false;
258
	for (int i=0; i<packageName.length; i++)
259
		if (!CharOperation.equals(packageName[i], typeName[i]))
260
			return false;
261
	return true;
262
}
263
264
void checkIfNullAnnotationType(ReferenceBinding type) {
265
	// check if type is one of the configured null annotation types
266
	// if so mark as a well known type using the corresponding typeID:
267
	if (this.environment.nullableAnnotationPackage == this
268
			&& CharOperation.equals(type.compoundName, this.environment.getNullableAnnotationName())) {
269
		type.id = TypeIds.T_ConfiguredAnnotationNullable;
270
		this.environment.nullableAnnotationPackage = null; // don't check again
271
	} else if (this.environment.nonnullAnnotationPackage == this
272
			&& CharOperation.equals(type.compoundName, this.environment.getNonNullAnnotationName())) {
273
		type.id = TypeIds.T_ConfiguredAnnotationNonNull;
274
		this.environment.nonnullAnnotationPackage = null; // don't check again
275
	} else if (this.environment.nonnullByDefaultAnnotationPackage == this
276
			&& CharOperation.equals(type.compoundName, this.environment.getNonNullByDefaultAnnotationName())) {
277
		type.id = TypeIds.T_ConfiguredAnnotationNonNullByDefault;
278
		this.environment.nonnullByDefaultAnnotationPackage = null; // don't check again
279
	}
280
}
281
282
public TypeBinding getNullnessDefaultAnnotation(Scope scope) {
283
	if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
284
		return this.nullnessDefaultAnnotation = this.environment.getNullAnnotationResolved(this.nullnessDefaultAnnotation, scope);
285
	return this.nullnessDefaultAnnotation;
286
}
287
233
public char[] readableName() /*java.lang*/ {
288
public char[] readableName() /*java.lang*/ {
234
	return CharOperation.concatWith(this.compoundName, '.');
289
	return CharOperation.concatWith(this.compoundName, '.');
235
}
290
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-2 / +12 lines)
Lines 4-13 Link Here
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
14
package org.eclipse.jdt.internal.compiler.lookup;
13
15
Lines 48-53 Link Here
48
		public boolean hasTypeBit(int bit) { return false; }
50
		public boolean hasTypeBit(int bit) { return false; }
49
	};
51
	};
50
52
53
	/**
54
	 * This faked annotation type binding marks types with unspecified nullness.
55
	 * For use in {@link PackageBinding#nullnessDefaultAnnotation} and SourceTypeBinding#nullnessDefaultAnnotation
56
	 */
57
	final static ReferenceBinding NULL_UNSPECIFIED = new ReferenceBinding() { /* faked type binding */
58
		public boolean hasTypeBit(int bit) { return false; }
59
	};
60
51
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
61
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
52
		public int compare(Object o1, Object o2) {
62
		public int compare(Object o1, Object o2) {
53
			char[] n1 = ((FieldBinding) o1).name;
63
			char[] n1 = ((FieldBinding) o1).name;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java (+15 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 4290-4293 Link Here
4290
		}
4291
		}
4291
		return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType);
4292
		return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType);
4292
	}
4293
	}
4294
4295
	public void validateNullAnnotation(long tagBits, TypeReference typeRef, Annotation[] annotations) {
4296
		long nullAnnotationTagBit = tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable);
4297
		if (nullAnnotationTagBit != 0) {
4298
			TypeBinding type = typeRef.resolvedType;
4299
			if (type != null && type.isBaseType()) {
4300
				char[][] annotationName = (nullAnnotationTagBit == TagBits.AnnotationNonNull)
4301
						? environment().getNonNullAnnotationName()
4302
						: environment().getNullableAnnotationName();
4303
				problemReporter().illegalAnnotationForBaseType(typeRef, annotations,
4304
						annotationName[annotationName.length-1], nullAnnotationTagBit);
4305
			}
4306
		}
4307
	}
4293
}
4308
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (-2 / +99 lines)
Lines 8-15 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
10
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
11
 *     							bug 328281 - visibility leaks not detected when analyzing unused field in private class
11
 *								bug 328281 - visibility leaks not detected when analyzing unused field in private class
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 54-59 Link Here
54
	char[] genericReferenceTypeSignature;
55
	char[] genericReferenceTypeSignature;
55
56
56
	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
57
	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
58
59
	private TypeBinding nullnessDefaultAnnotation;
60
	private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
57
61
58
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
62
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
59
	this.compoundName = compoundName;
63
	this.compoundName = compoundName;
Lines 781-786 Link Here
781
		}
785
		}
782
		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
786
		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
783
			this.modifiers |= ClassFileConstants.AccDeprecated;
787
			this.modifiers |= ClassFileConstants.AccDeprecated;
788
		evaluateNullAnnotations(this.tagBits);
784
	}
789
	}
785
	return this.tagBits;
790
	return this.tagBits;
786
}
791
}
Lines 1088-1093 Link Here
1088
			this.modifiers |= ClassFileConstants.AccDeprecated;
1093
			this.modifiers |= ClassFileConstants.AccDeprecated;
1089
		}
1094
		}
1090
	}
1095
	}
1096
	if (CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME))
1097
		getAnnotationTagBits(); // initialize
1091
}
1098
}
1092
1099
1093
// ensure the receiver knows its hierarchy & fields/methods so static imports can be resolved correctly
1100
// ensure the receiver knows its hierarchy & fields/methods so static imports can be resolved correctly
Lines 1590-1601 Link Here
1590
				typeParameters[i].binding = null;
1597
				typeParameters[i].binding = null;
1591
		return null;
1598
		return null;
1592
	}
1599
	}
1600
	createArgumentBindings(method);
1593
	if (foundReturnTypeProblem)
1601
	if (foundReturnTypeProblem)
1594
		return method; // but its still unresolved with a null return type & is still connected to its method declaration
1602
		return method; // but its still unresolved with a null return type & is still connected to its method declaration
1595
1603
1596
	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1604
	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1597
	return method;
1605
	return method;
1598
}
1606
}
1607
private void createArgumentBindings(MethodBinding method) {
1608
	// ensure nullness defaults are initialized at all enclosing levels:
1609
	switch (this.nullnessDefaultInitialized) {
1610
	case 0:
1611
		getAnnotationTagBits(); // initialize
1612
		//$FALL-THROUGH$
1613
	case 1:
1614
		getPackage().isViewedAsDeprecated(); // initialize annotations
1615
		this.nullnessDefaultInitialized = 2;
1616
	}
1617
	AbstractMethodDeclaration methodDecl = method.sourceMethod();
1618
	if (methodDecl != null) {
1619
		if (method.parameters != Binding.NO_PARAMETERS)
1620
			methodDecl.createArgumentBindings();
1621
		TypeBinding annotationBinding = findDefaultNullness(method, methodDecl.scope.environment());
1622
		if (annotationBinding != null && annotationBinding.id == TypeIds.T_ConfiguredAnnotationNonNull)
1623
			method.fillInDefaultNonNullness(annotationBinding);
1624
	}
1625
}
1626
private void evaluateNullAnnotations(long annotationTagBits) {
1627
	if (this.nullnessDefaultInitialized > 0)
1628
		return;
1629
	this.nullnessDefaultInitialized = 1;
1630
	// transfer nullness info from tagBits to this.nullnessDefaultAnnotation
1631
	TypeBinding defaultAnnotation = getPackage().environment
1632
						.getNullAnnotationBindingFromDefault(annotationTagBits, false/*resolve*/);
1633
	if (defaultAnnotation != null) {
1634
		if (CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME)) {
1635
			getPackage().nullnessDefaultAnnotation = defaultAnnotation;
1636
		} else {
1637
			this.nullnessDefaultAnnotation = defaultAnnotation;
1638
		}
1639
	}
1640
}
1641
private TypeBinding getNullnessDefaultAnnotation() {
1642
	if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
1643
		this.nullnessDefaultAnnotation = this.scope.environment().getNullAnnotationResolved(this.nullnessDefaultAnnotation, this.scope);
1644
	return this.nullnessDefaultAnnotation;
1645
}
1646
/**
1647
 * Answer the nullness default applicable at the given method binding.
1648
 * Possible values:<ul>
1649
 * <li>the type binding for @NonNulByDefault</li>
1650
 * <li>the synthetic type {@link ReferenceBinding#NULL_UNSPECIFIED} if a default from outer scope has been canceled</li>
1651
 * <li>null if no default has been defined</li>
1652
 * </ul>
1653
 */
1654
private TypeBinding findDefaultNullness(MethodBinding methodBinding, LookupEnvironment environment) {
1655
	// find the applicable default inside->out:
1656
1657
	// method
1658
	TypeBinding annotationBinding = environment.getNullAnnotationBindingFromDefault(methodBinding.tagBits, true/*resolve*/);
1659
	if (annotationBinding != null)
1660
		return annotationBinding;
1661
1662
	// type
1663
	ReferenceBinding type = methodBinding.declaringClass;
1664
	ReferenceBinding currentType = type;
1665
	while (currentType instanceof SourceTypeBinding) {
1666
		annotationBinding = ((SourceTypeBinding) currentType).getNullnessDefaultAnnotation();
1667
		if (annotationBinding != null)
1668
			return annotationBinding;
1669
		currentType = currentType.enclosingType();
1670
	}
1671
1672
	// package
1673
	annotationBinding = type.getPackage().getNullnessDefaultAnnotation(this.scope);
1674
	if (annotationBinding != null)
1675
		return annotationBinding;
1676
1677
	// global
1678
	long defaultNullness = environment.globalOptions.defaultNonNullness;
1679
	if (defaultNullness != 0) {
1680
		// we have a default, so we need an annotation type to record this during compile and in the byte code
1681
		annotationBinding = environment.getNullAnnotationBinding(defaultNullness, true/*resolve*/);
1682
		if (annotationBinding != null)
1683
			return annotationBinding;
1684
1685
		// on this branch default was not defined using an annotation, thus annotation type can still be missing
1686
		if (defaultNullness == TagBits.AnnotationNonNull)
1687
			this.scope.problemReporter().missingNullAnnotationType(environment.getNonNullAnnotationName());
1688
		else
1689
			this.scope.problemReporter().abortDueToInternalError("Illegal default nullness value: "+defaultNullness); //$NON-NLS-1$
1690
		// reset default to avoid duplicate errors:
1691
		environment.globalOptions.defaultNonNullness = 0;
1692
	}
1693
	return null;
1694
}
1695
1599
public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
1696
public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
1600
	if (forceInitialization)
1697
	if (forceInitialization)
1601
		binding.getAnnotationTagBits(); // ensure annotations are up to date
1698
		binding.getAnnotationTagBits(); // ensure annotations are up to date
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java (-3 / +16 lines)
Lines 7-12 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 132-137 Link Here
132
	long AnnotationPreDestroy = ASTNode.Bit54L;
133
	long AnnotationPreDestroy = ASTNode.Bit54L;
133
	/** @since 3.8 */
134
	/** @since 3.8 */
134
	long AnnotationPostConstruct = ASTNode.Bit55L;
135
	long AnnotationPostConstruct = ASTNode.Bit55L;
136
	/** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */
137
	long AnnotationNullable = ASTNode.Bit56L;
138
	/** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */
139
	long AnnotationNonNull = ASTNode.Bit57L;
140
	/** @since 3.8 null-default annotation for PackageBinding or TypeBinding or MethodBinding: */
141
	long AnnotationNonNullByDefault = ASTNode.Bit58L;
142
	/** @since 3.8 canceling null-default annotation for PackageBinding or TypeBinding or MethodBinding: */
143
	long AnnotationNullUnspecifiedByDefault = ASTNode.Bit59L;
135
144
136
	long AllStandardAnnotationsMask =
145
	long AllStandardAnnotationsMask =
137
				  AnnotationTargetMASK
146
				  AnnotationTargetMASK
Lines 144-153 Link Here
144
				| AnnotationSafeVarargs
153
				| AnnotationSafeVarargs
145
				| AnnotationPolymorphicSignature
154
				| AnnotationPolymorphicSignature
146
				| AnnotationPostConstruct
155
				| AnnotationPostConstruct
147
				| AnnotationPreDestroy;
156
				| AnnotationPreDestroy
157
				| AnnotationNullable
158
				| AnnotationNonNull
159
				| AnnotationNonNullByDefault
160
				| AnnotationNullUnspecifiedByDefault;
148
161
149
	long DefaultValueResolved = ASTNode.Bit56L;
162
	long DefaultValueResolved = ASTNode.Bit60L;
150
163
151
	// set when type contains non-private constructor(s)
164
	// set when type contains non-private constructor(s)
152
	long HasNonPrivateConstructor = ASTNode.Bit57L;
165
	long HasNonPrivateConstructor = ASTNode.Bit61L;
153
}
166
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (+6 lines)
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 104-109 Link Here
104
	final int T_JavaxAnnotationPostConstruct = 63;
105
	final int T_JavaxAnnotationPostConstruct = 63;
105
106
106
	final int T_JavaxAnnotationPreDestroy = 64;
107
	final int T_JavaxAnnotationPreDestroy = 64;
108
	
109
	// new in 3.8 for null annotations:
110
	final int T_ConfiguredAnnotationNullable = 65;
111
	final int T_ConfiguredAnnotationNonNull = 66;
112
	final int T_ConfiguredAnnotationNonNullByDefault = 67;
107
113
108
	final int NoId = Integer.MAX_VALUE;
114
	final int NoId = Integer.MAX_VALUE;
109
115
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java (-2 / +3 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.parser;
12
package org.eclipse.jdt.internal.compiler.parser;
12
13
Lines 546-556 Link Here
546
547
547
	if (this.lineEnds == null || this.linePtr == -1)
548
	if (this.lineEnds == null || this.linePtr == -1)
548
		return -1;
549
		return -1;
549
	if (lineNumber > this.lineEnds.length+1)
550
	if (lineNumber > this.linePtr + 2)
550
		return -1;
551
		return -1;
551
	if (lineNumber <= 0)
552
	if (lineNumber <= 0)
552
		return -1;
553
		return -1;
553
	if (lineNumber == this.lineEnds.length + 1)
554
	if (lineNumber == this.linePtr + 2)
554
		return this.eofPosition;
555
		return this.eofPosition;
555
	return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
556
	return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
556
}
557
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (-6 / +212 lines)
Lines 8-17 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contributions for 
11
 *     Stephan Herrmann  - Contributions for
12
 *     						bug 236385 - 
12
 *	     						bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
13
 *     						bug 338303 - Warning about Redundant assignment conflicts with definite assignment
13
 *  	   						bug 338303 - Warning about Redundant assignment conflicts with definite assignment
14
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
14
 *								bug 349326 - [1.7] new warning for missing try-with-resources
15
 *								bug 186342 - [compiler][null] Using annotations for null checking
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.problem;
17
package org.eclipse.jdt.internal.compiler.problem;
17
18
Lines 84-89 Link Here
84
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
85
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
85
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
86
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
86
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
87
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
88
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
87
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
89
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
88
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
90
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
89
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
91
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
Lines 287-292 Link Here
287
			return CompilerOptions.NullReference;
289
			return CompilerOptions.NullReference;
288
290
289
		case IProblem.PotentialNullLocalVariableReference:
291
		case IProblem.PotentialNullLocalVariableReference:
292
		case IProblem.PotentialNullMessageSendReference:
290
			return CompilerOptions.PotentialNullReference;
293
			return CompilerOptions.PotentialNullReference;
291
294
292
		case IProblem.RedundantLocalVariableNullAssignment:
295
		case IProblem.RedundantLocalVariableNullAssignment:
Lines 295-301 Link Here
295
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
298
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
296
		case IProblem.NullLocalVariableComparisonYieldsFalse:
299
		case IProblem.NullLocalVariableComparisonYieldsFalse:
297
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
300
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
301
		case IProblem.RedundantNullCheckOnNonNullMessageSend:
298
			return CompilerOptions.RedundantNullCheck;
302
			return CompilerOptions.RedundantNullCheck;
303
304
		case IProblem.RequiredNonNullButProvidedNull:
305
		case IProblem.IllegalReturnNullityRedefinition:
306
		case IProblem.IllegalRedefinitionToNonNullParameter:
307
		case IProblem.IllegalDefinitionToNonNullParameter:
308
		case IProblem.ParameterLackingNonNullAnnotation:
309
		case IProblem.ParameterLackingNullableAnnotation:
310
		case IProblem.CannotImplementIncompatibleNullness:
311
			return CompilerOptions.NullSpecViolation;
312
313
		case IProblem.RequiredNonNullButProvidedPotentialNull:
314
			return CompilerOptions.PotentialNullSpecViolation;
315
		case IProblem.RequiredNonNullButProvidedUnknown:
316
			return CompilerOptions.NullSpecInsufficientInfo;
317
		case IProblem.RedundantNullAnnotation:
318
			return CompilerOptions.RedundantNullAnnotation;
299
319
300
		case IProblem.BoxingConversion :
320
		case IProblem.BoxingConversion :
301
		case IProblem.UnboxingConversion :
321
		case IProblem.UnboxingConversion :
Lines 541-547 Link Here
541
			case CompilerOptions.ForbiddenReference :
561
			case CompilerOptions.ForbiddenReference :
542
			case CompilerOptions.DiscouragedReference :
562
			case CompilerOptions.DiscouragedReference :
543
				return CategorizedProblem.CAT_RESTRICTION;
563
				return CategorizedProblem.CAT_RESTRICTION;
544
			
564
565
			case CompilerOptions.NullSpecViolation :
566
			case CompilerOptions.PotentialNullSpecViolation :
567
			case CompilerOptions.NullSpecInsufficientInfo :
568
				return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
569
			case CompilerOptions.RedundantNullAnnotation :
570
				return CategorizedProblem.CAT_UNNECESSARY_CODE;
571
545
			default:
572
			default:
546
				break categorizeOnIrritant;
573
				break categorizeOnIrritant;
547
		}
574
		}
Lines 550-555 Link Here
550
	switch (problemID) {
577
	switch (problemID) {
551
		case IProblem.IsClassPathCorrect :
578
		case IProblem.IsClassPathCorrect :
552
		case IProblem.CorruptedSignature :
579
		case IProblem.CorruptedSignature :
580
		case IProblem.MissingNullAnnotationType :
553
			return CategorizedProblem.CAT_BUILDPATH;
581
			return CategorizedProblem.CAT_BUILDPATH;
554
582
555
		default :
583
		default :
Lines 8043-8046 Link Here
8043
		trackVar.sourceStart,
8071
		trackVar.sourceStart,
8044
		trackVar.sourceEnd);	
8072
		trackVar.sourceEnd);	
8045
}
8073
}
8046
}
8074
8075
public void nullityMismatch(Expression expression, TypeBinding requiredType, int nullStatus, char[][] annotationName) {
8076
	int problemId = IProblem.RequiredNonNullButProvidedUnknown;
8077
	if ((nullStatus & FlowInfo.NULL) != 0)
8078
		problemId = IProblem.RequiredNonNullButProvidedNull;
8079
	if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
8080
		problemId = IProblem.RequiredNonNullButProvidedPotentialNull;
8081
	String[] arguments = new String[] {
8082
			String.valueOf(CharOperation.concatWith(annotationName, '.')),
8083
			String.valueOf(requiredType.readableName())
8084
	};
8085
	String[] argumentsShort = new String[] {
8086
			String.valueOf(annotationName[annotationName.length-1]),
8087
			String.valueOf(requiredType.shortReadableName())
8088
	};
8089
	this.handle(
8090
		problemId,
8091
		arguments,
8092
		argumentsShort,
8093
		expression.sourceStart,
8094
		expression.sourceEnd);
8095
}
8096
public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
8097
	int sourceStart = argument.type.sourceStart;
8098
	if (argument.annotations != null) {
8099
		for (int i=0; i<argument.annotations.length; i++) {
8100
			Annotation annotation = argument.annotations[i];
8101
			if (   annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable
8102
				|| annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull)
8103
			{
8104
				sourceStart = annotation.sourceStart;
8105
				break;
8106
			}
8107
		}
8108
	}
8109
	if (inheritedAnnotationName == null) {
8110
		this.handle(
8111
			IProblem.IllegalDefinitionToNonNullParameter, 
8112
			new String[] { new String(argument.name), new String(declaringClass.readableName()) },
8113
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()) },
8114
			sourceStart,
8115
			argument.type.sourceEnd);
8116
	} else {
8117
		this.handle(
8118
			IProblem.IllegalRedefinitionToNonNullParameter, 
8119
			new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8120
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8121
			sourceStart,
8122
			argument.type.sourceEnd);
8123
	}
8124
}
8125
public void parameterLackingNonNullAnnotation(Argument argument, ReferenceBinding declaringClass, boolean needNonNull, char[][] inheritedAnnotationName) {
8126
	this.handle(
8127
		needNonNull ? IProblem.ParameterLackingNonNullAnnotation : IProblem.ParameterLackingNullableAnnotation, 
8128
		new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8129
		new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8130
		argument.type.sourceStart,
8131
		argument.type.sourceEnd);
8132
}
8133
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl,
8134
									  MethodBinding inheritedMethod, char[][] nonNullAnnotationName)
8135
{
8136
	MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl;
8137
	StringBuffer methodSignature = new StringBuffer();
8138
	methodSignature
8139
		.append(inheritedMethod.declaringClass.readableName())
8140
		.append('.')
8141
		.append(inheritedMethod.readableName());
8142
8143
	StringBuffer shortSignature = new StringBuffer();
8144
	shortSignature
8145
		.append(inheritedMethod.declaringClass.shortReadableName())
8146
		.append('.')
8147
		.append(inheritedMethod.shortReadableName());
8148
	int sourceStart = methodDecl.returnType.sourceStart;
8149
	Annotation[] annotations = methodDecl.annotations;
8150
	if (annotations != null) {
8151
		for (int i=0; i<annotations.length; i++) {
8152
			if (annotations[i].resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable) {
8153
				sourceStart = annotations[i].sourceStart;
8154
				break;
8155
			}
8156
		}
8157
	}
8158
	this.handle(
8159
		IProblem.IllegalReturnNullityRedefinition, 
8160
		new String[] { methodSignature.toString(), CharOperation.toString(nonNullAnnotationName)},
8161
		new String[] { shortSignature.toString(), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])},
8162
		sourceStart,
8163
		methodDecl.returnType.sourceEnd);
8164
}
8165
public void messageSendPotentialNullReference(MethodBinding method, ASTNode location) {
8166
	String[] arguments = new String[] {new String(method.readableName())};
8167
	this.handle(
8168
		IProblem.PotentialNullMessageSendReference,
8169
		arguments,
8170
		arguments,
8171
		location.sourceStart,
8172
		location.sourceEnd);
8173
}
8174
public void messageSendRedundantCheckOnNonNull(MethodBinding method, ASTNode location) {
8175
	String[] arguments = new String[] {new String(method.readableName())  };
8176
	this.handle(
8177
		IProblem.RedundantNullCheckOnNonNullMessageSend,
8178
		arguments,
8179
		arguments,
8180
		location.sourceStart,
8181
		location.sourceEnd);
8182
}
8183
8184
public void missingNullAnnotationType(char[][] nullAnnotationName) {
8185
	String[] args = { new String(CharOperation.concatWith(nullAnnotationName, '.')) };
8186
	this.handle(IProblem.MissingNullAnnotationType, args, args, 0, 0);
8187
}
8188
8189
public void cannotImplementIncompatibleNullness(MethodBinding currentMethod, MethodBinding inheritedMethod) {
8190
	int sourceStart = 0, sourceEnd = 0;
8191
	if (this.referenceContext instanceof TypeDeclaration) {
8192
		sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart;
8193
		sourceEnd =   ((TypeDeclaration) this.referenceContext).sourceEnd;
8194
	}
8195
	String[] problemArguments = {
8196
			new String(currentMethod.readableName()),
8197
			new String(currentMethod.declaringClass.readableName()),
8198
			new String(inheritedMethod.declaringClass.readableName())
8199
		};
8200
	String[] messageArguments = {
8201
			new String(currentMethod.shortReadableName()),
8202
			new String(currentMethod.declaringClass.shortReadableName()),
8203
			new String(inheritedMethod.declaringClass.shortReadableName())
8204
		};
8205
	this.handle(
8206
			IProblem.CannotImplementIncompatibleNullness,
8207
			problemArguments,
8208
			messageArguments,
8209
			sourceStart,
8210
			sourceEnd);
8211
}
8212
8213
public void nullAnnotationIsRedundant(AbstractMethodDeclaration sourceMethod, int i) {
8214
	int sourceStart, sourceEnd;
8215
	if (i == -1) {
8216
		MethodDeclaration methodDecl = (MethodDeclaration) sourceMethod;
8217
		sourceStart = findAnnotationSourceStart(methodDecl.annotations, methodDecl.returnType.sourceStart, TypeIds.T_ConfiguredAnnotationNonNull);
8218
		sourceEnd = methodDecl.returnType.sourceEnd;
8219
	} else {
8220
		Argument arg = sourceMethod.arguments[i];
8221
		sourceStart = arg.declarationSourceStart;
8222
		sourceEnd = arg.sourceEnd;
8223
	}
8224
	this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
8225
}
8226
8227
public void illegalAnnotationForBaseType(TypeReference type, Annotation[] annotations, char[] annotationName, long nullAnnotationTagBit)
8228
{
8229
	int typeId = (nullAnnotationTagBit == TagBits.AnnotationNullable) 
8230
			? TypeIds.T_ConfiguredAnnotationNullable : TypeIds.T_ConfiguredAnnotationNonNull;
8231
	String[] args = new String[] { new String(annotationName), new String(type.getLastToken()) };
8232
	this.handle(IProblem.IllegalAnnotationForBaseType,
8233
			args,
8234
			args,
8235
			findAnnotationSourceStart(annotations, type.sourceStart, typeId),
8236
			type.sourceEnd);
8237
}
8238
8239
private int findAnnotationSourceStart(Annotation[] annotations, int startFallback, int typeId) {
8240
	int sourceStart = startFallback;
8241
	if (annotations != null) {
8242
		// should have a @NonNull/@Nullable annotation, search for it:
8243
		for (int j=0; j<annotations.length; j++) {
8244
			if (annotations[j].resolvedType.id == typeId) {
8245
				sourceStart = annotations[j].sourceStart;
8246
				break;
8247
			}
8248
		}
8249
	}
8250
	return sourceStart;
8251
}
8252
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+17 lines)
Lines 11-16 Link Here
11
#		Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
11
#		Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
12
#							bug 185682 - Increment/decrement operators mark local variables as read
12
#							bug 185682 - Increment/decrement operators mark local variables as read
13
#							bug 349326 - [1.7] new warning for missing try-with-resources
13
#							bug 349326 - [1.7] new warning for missing try-with-resources
14
#							bug 186342 - [compiler][null] Using annotations for null checking
14
###############################################################################
15
###############################################################################
15
0 = {0}
16
0 = {0}
16
1 = super cannot be used in java.lang.Object
17
1 = super cannot be used in java.lang.Object
Lines 655-660 Link Here
655
889 = Resource ''{0}'' should be managed by try-with-resource
656
889 = Resource ''{0}'' should be managed by try-with-resource
656
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
657
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
657
658
659
### NULL ANNOTATIONS
660
910 = Type mismatch: required ''@{0} {1}'' but the provided value is null
661
911 = Type mismatch: required ''@{0} {1}'' but the provided value can be null
662
912 = Potential type mismatch: required ''@{0} {1}'' but nullness of the provided value is unknown
663
913 = Buildpath problem: the type {0}, which is configured as a null annotation type, cannot be resolved
664
914 = The return type is incompatible with the @{1} return from {0}
665
915 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
666
916 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
667
917 = Missing non-null annotation: inherited method from {1} declares this parameter as @{2}
668
918 = Missing nullable annotation: inherited method from {1} declares this parameter as @{2}
669
919 = Potential null pointer access: The method {0} may return null
670
920 = Redundant null check: The method {0} cannot return null
671
921 = The method {0} from {1} cannot implement the corresponding method from {2} due to incompatible nullness constraints
672
922 = The nullness annotation is redundant with a default that applies to this location
673
923 = The nullness annotation @{0} is not applicable for the primitive type {1}
674
658
### ELABORATIONS
675
### ELABORATIONS
659
## Access restrictions
676
## Access restrictions
660
78592 = The type {1} is not accessible due to restriction on classpath entry {0}
677
78592 = The type {1} is not accessible due to restriction on classpath entry {0}
(-)a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java (-5 / +13 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 363858 - [dom] early throwing of AbortCompilation causes NPE in CompilationUnitResolver
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.core.dom;
12
package org.eclipse.jdt.core.dom;
12
13
Lines 99-104 Link Here
99
	DefaultBindingResolver.BindingTables bindingTables;
100
	DefaultBindingResolver.BindingTables bindingTables;
100
101
101
	boolean hasCompilationAborted;
102
	boolean hasCompilationAborted;
103
	CategorizedProblem abortProblem;
102
104
103
	private IProgressMonitor monitor;
105
	private IProgressMonitor monitor;
104
	
106
	
Lines 364-369 Link Here
364
			removeUnresolvedBindings(unit);
366
			removeUnresolvedBindings(unit);
365
		}
367
		}
366
		this.hasCompilationAborted = true;
368
		this.hasCompilationAborted = true;
369
		this.abortProblem = abortException.problem;
367
	}
370
	}
368
371
369
	public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
372
	public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
Lines 689-699 Link Here
689
				// the bindings could not be resolved due to missing types in name environment
692
				// the bindings could not be resolved due to missing types in name environment
690
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
693
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
691
				CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
694
				CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
692
				final int problemCount = unit.compilationResult.problemCount;
695
				if (unit != null) {
693
				if (problemCount != 0) {
696
					final int problemCount = unit.compilationResult.problemCount;
694
					unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
697
					if (problemCount != 0) {
695
					System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
698
						unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
696
					unitDeclaration.compilationResult.problemCount = problemCount;
699
						System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
700
						unitDeclaration.compilationResult.problemCount = problemCount;
701
					}
702
				} else if (resolver.abortProblem != null) {
703
					unitDeclaration.compilationResult.problemCount = 1;
704
					unitDeclaration.compilationResult.problems = new CategorizedProblem[] { resolver.abortProblem };
697
				}
705
				}
698
				return unitDeclaration;
706
				return unitDeclaration;
699
			}
707
			}
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java (+213 lines)
Lines 87-92 Link Here
87
 *     								COMPILER_PB_UNCLOSED_CLOSEABLE,
87
 *     								COMPILER_PB_UNCLOSED_CLOSEABLE,
88
 *     								COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE
88
 *     								COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE
89
 *     								COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE
89
 *     								COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE
90
 *     								COMPILER_ANNOTATION_NULL_ANALYSIS
91
 *     								COMPILER_NULLABLE_ANNOTATION_NAME
92
 *     								COMPILER_NONNULL_ANNOTATION_NAME
93
 *     								COMPILER_PB_NULL_SPECIFICATION_VIOLATION
94
 *     								COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION
95
 *     								COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO
90
 *******************************************************************************/
96
 *******************************************************************************/
91
97
92
package org.eclipse.jdt.core;
98
package org.eclipse.jdt.core;
Lines 1407-1412 Link Here
1407
	 */
1413
	 */
1408
	public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
1414
	public static final String COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE = PLUGIN_ID + ".compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
1409
	/**
1415
	/**
1416
	 * Compiler option ID: Annotation-based Null Analysis.
1417
	 * <p>This option controls whether the compiler will use null annotations for
1418
	 *    improved analysis of (potential) null references.</p>
1419
	 * <p>If enabled the compiler will interpret the annotation types defined using
1420
	 *    {@link #COMPILER_NONNULL_ANNOTATION_NAME} and {@link #COMPILER_NULLABLE_ANNOTATION_NAME}
1421
	 *    as specifying whether or not a given type includes the value <code>null</code>.</p>
1422
	 * <p>The effect of these analyses is further controled by the options
1423
	 *    {@link #COMPILER_PB_NULL_SPECIFICATION_VIOLATION},
1424
	 *    {@link #COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION} and
1425
	 *    {@link #COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO}.
1426
	 * </p>
1427
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.annotation.nullanalysis"</code></dd>
1428
	 * <dt>Possible values:</dt><dd><code>{ "disabled", "enabled" }</dd>
1429
	 * <dt>Default:</dt><dd><code>"disabled"</code></dd>
1430
	 * @since 3.8
1431
	 * @category CompilerOptionID
1432
	 */
1433
	public static final String COMPILER_ANNOTATION_NULL_ANALYSIS = PLUGIN_ID + ".compiler.annotation.nullanalysis"; //$NON-NLS-1$
1434
	/**
1435
	 * Compiler option ID: Name of Annotation Type for Nullable Types.
1436
	 * <p>This option defines a fully qualified Java type name that the compiler may use
1437
	 *    to perform special null analysis.</p>
1438
	 * <p>If the annotation specified by this option is applied to a type in a method
1439
	 *    signature or variable declaration this will be interpreted as a specification
1440
	 *    that <code>null</code> is a legal value in that position. Currently supported
1441
	 *    positions are: method parameters, method return type and local variables.</p>
1442
	 * <p>If a value whose type
1443
	 *    is annotated with this annotation is dereferenced without checking for null
1444
	 *    the compiler will trigger a diagnostic as further controlled by
1445
	 *    {@link #COMPILER_PB_POTENTIAL_NULL_REFERENCE}.</p>
1446
	 * <p>The compiler may furthermore check adherence to the null specification as
1447
	 *    further controlled by {@link #COMPILER_PB_NULL_SPECIFICATION_VIOLATION},
1448
	 *    {@link #COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION} and
1449
	 *    {@link #COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO}.
1450
	 * </p>
1451
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.annotation.nullable"</code></dd>
1452
	 * <dt>Possible values:</dt><dd>any legal, fully qualified Java type name, must resolve to an annotation type.</dd>
1453
	 * <dt>Default:</dt><dd><code>"org.eclipse.jdt.annotation.Nullable"</code></dd>
1454
	 * @since 3.8
1455
	 * @category CompilerOptionID
1456
	 */
1457
	public static final String COMPILER_NULLABLE_ANNOTATION_NAME = PLUGIN_ID + ".compiler.annotation.nullable"; //$NON-NLS-1$
1458
	/**
1459
	 * Compiler option ID: Name of Annotation Type for Non-Null Types.
1460
	 * <p>This option defines a fully qualified Java type name that the compiler may use
1461
	 *    to perform special null analysis.</p>
1462
	 * <p>If the annotation specified by this option is applied to a type in a method
1463
	 *    signature or variable declaration this will be interpreted as a specification
1464
	 *    that <code>null</code> is <b>not</b> a legal value in that position. Currently
1465
	 *    supported positions are: method parameters, method return type and local variables.</p>
1466
	 * <p>For values declared with this annotation the compiler will never trigger a null
1467
	 *    reference diagnostic (as controlled by {@link #COMPILER_PB_POTENTIAL_NULL_REFERENCE}
1468
	 *    and {@link #COMPILER_PB_NULL_REFERENCE}), because the assumption is made that null
1469
	 *    will never occur at runtime in these positions.</p>
1470
	 * <p>The compiler may furthermore check adherence to the null specification as further
1471
	 *    controlled by {@link #COMPILER_PB_NULL_SPECIFICATION_VIOLATION},
1472
	 *    {@link #COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION} and
1473
	 *    {@link #COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO}.
1474
	 * </p>
1475
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.annotation.nonnull"</code></dd>
1476
	 * <dt>Possible values:</dt><dd>any legal, fully qualified Java type name, must resolve to an annotation type.</dd>
1477
	 * <dt>Default:</dt><dd><code>"org.eclipse.jdt.annotation.NonNull"</code></dd>
1478
	 * @since 3.8
1479
	 * @category CompilerOptionID
1480
	 */
1481
	public static final String COMPILER_NONNULL_ANNOTATION_NAME = PLUGIN_ID + ".compiler.annotation.nonnull"; //$NON-NLS-1$
1482
	/**
1483
	 * Compiler option ID: Name of Annotation Type to specify a nullness default for unannotated types.
1484
	 * <p>This option defines a fully qualified Java type name that the compiler may use
1485
	 *    to perform special null analysis.</p>
1486
	 * <p>If the annotation is applied without an argument all unannotated types in method signatures
1487
	 *    within the annotated element will be treated as if they were specified with the non-null annotation
1488
	 *    (see {@link #COMPILER_NONNULL_ANNOTATION_NAME}).</p>
1489
	 * <p>If the annotation is applied without the constant <code>false</code> as its argument
1490
	 *    all corresponding defaults at outer scopes will be canceled for the annotated element.
1491
	 *    This includes defaults specified using this annotation type or a default defined using
1492
	 *    the compiler option {@link #COMPILER_NONNULL_IS_DEFAULT}.</p>
1493
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.annotation.nonnullbydefault"</code></dd>
1494
	 * <dt>Possible values:</dt><dd>any legal, fully qualified Java type name, must resolve to an annotation type.
1495
	 *     That annotation type should have exactly one boolean parameter.</dd>
1496
	 * <dt>Default:</dt><dd><code>"org.eclipse.jdt.annotation.NonNullByDefault"</code></dd>
1497
	 * @since 3.8
1498
	 * @category CompilerOptionID
1499
	 */
1500
	public static final String COMPILER_NONNULL_BY_DEFAULT_ANNOTATION_NAME = PLUGIN_ID + ".compiler.annotation.nonnullbydefault"; //$NON-NLS-1$
1501
	/**
1502
	 * Compiler option ID: Globally specify non-null as the assumed default for unannotated types.
1503
	 * <p>When enabled this option globally achieves the same effect 
1504
	 *    as specifying {@link #COMPILER_NONNULL_ANNOTATION_NAME} does for individual elements.</p>
1505
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.annotation.nonnullisdefault"</code></dd>
1506
	 * <dt>Possible values:</dt><dd><code>{ "disabled", "enabled" }</code>.</dd>
1507
	 * <dt>Default:</dt><dd><code>"disabled"</code></dd>
1508
	 * @since 3.8
1509
	 * @category CompilerOptionID
1510
	 */
1511
	public static final String COMPILER_NONNULL_IS_DEFAULT = PLUGIN_ID + ".compiler.annotation.nonnullisdefault"; //$NON-NLS-1$
1512
	/**
1513
	 * Compiler option ID: Reporting Violations of Null Specifications.
1514
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the
1515
	 *    following situations is detected:
1516
	 *    <ol>
1517
	 *    <li>A method declared with a nonnull annotation returns an expression	that is
1518
	 *          statically known to evaluate to a null value.</li>
1519
	 *    <li>An expression that is statically known to evaluate to a null value is	passed
1520
	 *        as an argument in a method call where the corresponding parameter of the called
1521
	 *        method is declared with a nonnull annotation.</li>
1522
	 *    <li>An expression that is statically known to evaluate to a null value is	assigned
1523
	 *        to a local variable that is declared with a nonnull annotation.</li>
1524
	 *    <li>A method that overrides an inherited method declared with a nonnull annotation
1525
	 *        tries to relax that contract by specifying a nullable annotation
1526
	 *        (prohibition of contravariant return).</li>
1527
	 *    <li>A method that overrides an inherited method which has a nullable declaration
1528
	 *        for at least one of its parameters, tries to tighten that null contract by
1529
	 *        specifying a nonnull annotation for its corresponding parameter
1530
	 *        (prohibition of covariant parameters).</li>
1531
	 *    </ol>
1532
	 * </p>
1533
	 * <p>The compiler options {@link #COMPILER_NONNULL_ANNOTATION_NAME} and
1534
	 *    {@link #COMPILER_NULLABLE_ANNOTATION_NAME} control which annotations the compiler
1535
	 *    shall interpret as nonnull or nullable annotations, respectively.
1536
	 * </p>
1537
	 * <dl>
1538
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.nullContractViolation"</code></dd>
1539
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1540
	 * <dt>Default:</dt><dd><code>"error"</code></dd>
1541
	 * </dl>
1542
	 * @since 3.8
1543
	 * @category CompilerOptionID
1544
	 */
1545
	public static final String COMPILER_PB_NULL_SPECIFICATION_VIOLATION = PLUGIN_ID + ".compiler.problem.nullSpecViolation"; //$NON-NLS-1$
1546
	/**
1547
	 * Compiler option ID: Reporting Violations of Null Specifications with Potential Null Value.
1548
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the
1549
	 *    following situations is detected:
1550
	 *    <ol>
1551
	 *    <li>A method declared with a nonnull annotation returns an expression that is
1552
	 *          statically known to evaluate to a null value on some flow.</li>
1553
	 *    <li>An expression that is statically known to evaluate to a null value on some flow
1554
	 *        is passed as an argument in a method call where the corresponding parameter of
1555
	 *        the called method is declared with a nonnull annotation.</li>
1556
	 *    <li>An expression that is statically known to evaluate to a null value on some flow
1557
	 *        is assigned to a local variable that is declared with a nonnull annotation.</li>
1558
	 *    </ol>
1559
	 * </p>
1560
	 * <p>The compiler options {@link #COMPILER_NONNULL_ANNOTATION_NAME} and
1561
	 *    {@link #COMPILER_NULLABLE_ANNOTATION_NAME} control which annotations the compiler
1562
	 *    shall interpret as nonnull or nullable annotations, respectively.
1563
	 * </p>
1564
	 * <dl>
1565
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation"</code></dd>
1566
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1567
	 * <dt>Default:</dt><dd><code>"error"</code></dd>
1568
	 * </dl>
1569
	 * @since 3.8
1570
	 * @category CompilerOptionID
1571
	 */
1572
	public static final String COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION = PLUGIN_ID + ".compiler.problem.potentialNullSpecViolation"; //$NON-NLS-1$
1573
	/**
1574
	 * Compiler option ID: Reporting Insufficient Information for Analysing Adherence to Null Specifications.
1575
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the
1576
	 *    following situations is detected:
1577
	 *    <ol>
1578
	 *    <li>A method declared with a nonnull annotation returns an expression for	which
1579
	 *        insufficient nullness information is available for statically proving that no
1580
	 *        flow will pass a null value at runtime.</li>
1581
	 *    <li>An expression for which insufficient nullness information is available for
1582
	 *        statically proving that it will never evaluate to a null value at runtime
1583
	 *        is passed as an argument in a method call where the corresponding	parameter of
1584
	 *        the called method is declared with a nonnull annotation.</li>
1585
	 *    <li>An expression for which insufficient nullness information is available for
1586
	 *        statically proving that it will never evaluate to a null value at runtime
1587
	 *        is assigned to a local variable that is declared with a nonnull annotation.</li>
1588
	 *    </ol>
1589
	 *    Insufficient nullness information is usually a consequence of using other unannotated
1590
	 *    variables or methods.
1591
	 * </p>
1592
	 * <p>The compiler options {@link #COMPILER_NONNULL_ANNOTATION_NAME} and
1593
	 *    {@link #COMPILER_NULLABLE_ANNOTATION_NAME} control which annotations the compiler
1594
	 *    shall interpret as nonnull or nullable annotations, respectively.
1595
	 * </p>
1596
	 * <dl>
1597
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo"</code></dd>
1598
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1599
	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
1600
	 * </dl>
1601
	 * @since 3.8
1602
	 * @category CompilerOptionID
1603
	 */
1604
	public static final String COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO = PLUGIN_ID + ".compiler.problem.nullSpecInsufficientInfo"; //$NON-NLS-1$
1605
	/**
1606
	 * Compiler option ID: Reporting Redundant Null Annotations.
1607
	 * <p>When enabled, the compiler will issue an error or a warning when a non-null annotation
1608
	 *    (see {@link #COMPILER_NONNULL_ANNOTATION_NAME})
1609
	 *    is applied although the same effect is already achieved by a default applicable at the
1610
	 *    current location. Such default may be effective by enabling the option
1611
	 *    {@link #COMPILER_NONNULL_IS_DEFAULT} or by using the annotation specified by the option
1612
	 *    {@link #COMPILER_NONNULL_BY_DEFAULT_ANNOTATION_NAME}.
1613
	 * </p>
1614
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation"</code></dd>
1615
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1616
	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
1617
	 * </dl>
1618
	 * @since 3.8
1619
	 * @category CompilerOptionID
1620
	 */
1621
	public static final String COMPILER_PB_REDUNDANT_NULL_ANNOTATION = PLUGIN_ID + ".compiler.problem.redundantNullAnnotation"; //$NON-NLS-1$
1622
	/**
1410
	 * Compiler option ID: Setting Source Compatibility Mode.
1623
	 * Compiler option ID: Setting Source Compatibility Mode.
1411
	 * <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
1624
	 * <p>Specify whether which source level compatibility is used. From 1.4 on, <code>'assert'</code> is a keyword
1412
	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
1625
	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java (-1 / +1 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java (-1 / +1 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at

Return to bug 186342