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 (+31 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 729-734 Link Here
729
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
736
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
730
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
737
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
731
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
738
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
739
		expectedProblemAttributes.put("NullAnnotationNameMustBeQualified", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
732
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
740
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
733
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
741
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
734
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
742
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
Lines 745-750 Link Here
745
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
753
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
746
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
754
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
747
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
755
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
756
		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
757
		expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
748
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
758
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
749
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
759
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
750
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
760
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
Lines 771-776 Link Here
771
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
781
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
772
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
782
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
773
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
783
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
784
		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
774
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
785
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
775
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
786
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
776
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
787
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
Lines 779-788 Link Here
779
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
790
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
780
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
791
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
781
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
792
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
793
		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
782
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
794
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
795
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
783
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
796
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
784
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
797
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
785
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
798
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
799
		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
800
		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
801
		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
786
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
802
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
787
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
803
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
788
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
804
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
Lines 1056-1061 Link Here
1056
		expectedProblemAttributes.put("CannotExtendEnum", SKIP);
1072
		expectedProblemAttributes.put("CannotExtendEnum", SKIP);
1057
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", SKIP);
1073
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", SKIP);
1058
		expectedProblemAttributes.put("CannotImportPackage", SKIP);
1074
		expectedProblemAttributes.put("CannotImportPackage", SKIP);
1075
		expectedProblemAttributes.put("CannotImplementIncompatibleNullness", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1059
		expectedProblemAttributes.put("CannotInferElidedTypes", SKIP);
1076
		expectedProblemAttributes.put("CannotInferElidedTypes", SKIP);
1060
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", SKIP);
1077
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", SKIP);
1061
		expectedProblemAttributes.put("CannotOverrideAStaticMethodWithAnInstanceMethod", SKIP);
1078
		expectedProblemAttributes.put("CannotOverrideAStaticMethodWithAnInstanceMethod", SKIP);
Lines 1145-1152 Link Here
1145
		expectedProblemAttributes.put("HierarchyHasProblems", SKIP);
1162
		expectedProblemAttributes.put("HierarchyHasProblems", SKIP);
1146
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", SKIP);
1163
		expectedProblemAttributes.put("IllegalAbstractModifierCombinationForMethod", SKIP);
1147
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", SKIP);
1164
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", SKIP);
1165
		expectedProblemAttributes.put("IllegalAnnotationForBaseType", SKIP);
1148
		expectedProblemAttributes.put("IllegalCast", SKIP);
1166
		expectedProblemAttributes.put("IllegalCast", SKIP);
1149
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", SKIP);
1167
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", SKIP);
1168
		expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1150
		expectedProblemAttributes.put("IllegalDimension", SKIP);
1169
		expectedProblemAttributes.put("IllegalDimension", SKIP);
1151
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", SKIP);
1170
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", SKIP);
1152
		expectedProblemAttributes.put("IllegalExtendedDimensions", SKIP);
1171
		expectedProblemAttributes.put("IllegalExtendedDimensions", SKIP);
Lines 1181-1186 Link Here
1181
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1200
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1182
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1201
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1183
		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));
1184
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1205
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1185
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1206
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1186
		expectedProblemAttributes.put("IllegalUnderscorePosition", SKIP);
1207
		expectedProblemAttributes.put("IllegalUnderscorePosition", SKIP);
Lines 1364-1369 Link Here
1364
		expectedProblemAttributes.put("MissingEnclosingInstance", SKIP);
1385
		expectedProblemAttributes.put("MissingEnclosingInstance", SKIP);
1365
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", SKIP);
1386
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", SKIP);
1366
		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);
1367
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1389
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1368
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1390
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION));
1369
		expectedProblemAttributes.put("MissingReturnType", SKIP);
1391
		expectedProblemAttributes.put("MissingReturnType", SKIP);
Lines 1404-1409 Link Here
1404
		expectedProblemAttributes.put("NotVisibleField", SKIP);
1426
		expectedProblemAttributes.put("NotVisibleField", SKIP);
1405
		expectedProblemAttributes.put("NotVisibleMethod", SKIP);
1427
		expectedProblemAttributes.put("NotVisibleMethod", SKIP);
1406
		expectedProblemAttributes.put("NotVisibleType", SKIP);
1428
		expectedProblemAttributes.put("NotVisibleType", SKIP);
1429
		expectedProblemAttributes.put("NullAnnotationNameMustBeQualified", SKIP);
1407
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1430
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1408
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1431
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1409
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
1432
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
Lines 1420-1425 Link Here
1420
		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
1443
		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
1421
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
1444
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
1422
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
1445
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
1446
		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1447
		expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1423
		expectedProblemAttributes.put("ParameterMismatch", SKIP);
1448
		expectedProblemAttributes.put("ParameterMismatch", SKIP);
1424
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", SKIP);
1449
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", SKIP);
1425
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", SKIP);
1450
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", SKIP);
Lines 1446-1451 Link Here
1446
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1471
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1447
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1472
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE));
1448
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1473
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1474
		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1449
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1475
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1450
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1476
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1451
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
1477
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
Lines 1454-1464 Link Here
1454
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1480
		expectedProblemAttributes.put("RedefinedLocal", SKIP);
1455
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
1481
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_TYPE_ARGUMENTS));
1456
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1482
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1483
		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION));
1457
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1484
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1485
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1458
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1486
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1459
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1487
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_SUPERINTERFACE));
1460
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
1488
		expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
1461
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
1489
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
1490
		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
1491
		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_SPECIFICATION_VIOLATION));
1492
		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_INSUFFICIENT_INFO));
1462
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", SKIP);
1493
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", SKIP);
1463
		expectedProblemAttributes.put("ReturnTypeAmbiguous", SKIP);
1494
		expectedProblemAttributes.put("ReturnTypeAmbiguous", SKIP);
1464
		expectedProblemAttributes.put("ReturnTypeCannotBeVoidArray", SKIP);
1495
		expectedProblemAttributes.put("ReturnTypeCannotBeVoidArray", SKIP);
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java (+2213 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
public void test_illegal_annotation_002() {
1523
	Map customOptions = getCompilerOptions();
1524
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "NichtNull");
1525
	runNegativeTestWithLibs(
1526
		new String[] {
1527
			"X.java",
1528
			"public class X {\n" +
1529
			"}\n"
1530
		},
1531
		customOptions,
1532
		"----------\n" + 
1533
		"1. ERROR in X.java (at line 1)\n" + 
1534
		"	public class X {\n" + 
1535
		"	^\n" + 
1536
		"Cannot use the unqualified name \'NichtNull\' as an annotation name for null specification\n" + 
1537
		"----------\n");
1538
}
1539
1540
// a null annotation is illegally used on a void method:
1541
public void test_illegal_annotation_003() {
1542
	runNegativeTest(
1543
		new String[] {
1544
			"X.java",
1545
			"import org.eclipse.jdt.annotation.*;\n" +
1546
			"public class X {\n" +
1547
			"	@NonNull void foo() {}\n" +
1548
			"}\n"
1549
		},
1550
		"----------\n" + 
1551
		"1. ERROR in X.java (at line 3)\n" + 
1552
		"	@NonNull void foo() {}\n" + 
1553
		"	^^^^^^^^^^^^^\n" + 
1554
		"The nullness annotation @NonNull is not applicable for the primitive type void\n" + 
1555
		"----------\n",
1556
		this.LIBS,
1557
		false/*shouldFlush*/);
1558
}
1559
1560
// a null annotation is illegally used on a primitive type parameter
1561
public void test_illegal_annotation_004() {
1562
	runNegativeTest(
1563
		new String[] {
1564
			"X.java",
1565
			"import org.eclipse.jdt.annotation.*;\n" +
1566
			"public class X {\n" +
1567
			"	void foo(@Nullable int i) {}\n" +
1568
			"}\n"
1569
		},
1570
		"----------\n" + 
1571
		"1. ERROR in X.java (at line 3)\n" + 
1572
		"	void foo(@Nullable int i) {}\n" + 
1573
		"	         ^^^^^^^^^^^^^\n" + 
1574
		"The nullness annotation @Nullable is not applicable for the primitive type int\n" + 
1575
		"----------\n",
1576
		this.LIBS,
1577
		false/*shouldFlush*/);
1578
}
1579
1580
// a null annotation is illegally used on a primitive type local var
1581
public void test_illegal_annotation_005() {
1582
	runNegativeTest(
1583
		new String[] {
1584
			"X.java",
1585
			"import org.eclipse.jdt.annotation.*;\n" +
1586
			"public class X {\n" +
1587
			"	int foo() {\n" +
1588
			"       @Nullable int i = 3;\n" +
1589
			"       return i;\n" +
1590
			"   }\n" + 
1591
			"}\n"
1592
		},
1593
		"----------\n" + 
1594
		"1. ERROR in X.java (at line 4)\n" + 
1595
		"	@Nullable int i = 3;\n" + 
1596
		"	^^^^^^^^^^^^^\n" + 
1597
		"The nullness annotation @Nullable is not applicable for the primitive type int\n" + 
1598
		"----------\n",
1599
		this.LIBS,
1600
		false/*shouldFlush*/);
1601
}
1602
1603
// a configured annotation type does not exist
1604
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342#c133
1605
public void test_illegal_annotation_006() {
1606
	Map customOptions = getCompilerOptions();
1607
	customOptions.put(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, "nullAnn.Nullable");
1608
	runNegativeTestWithLibs(
1609
		new String[] {
1610
			"p/Test.java",
1611
			"package p;\n" + 
1612
			"import nullAnn.*;  // 1 \n" + 
1613
			"\n" + 
1614
			"public class Test { \n" + 
1615
			"\n" + 
1616
			"        void foo(@nullAnn.Nullable  Object o) {   // 2\n" + 
1617
			"            o.toString();           \n" + 
1618
			"        }\n" + 
1619
			"}"
1620
		},
1621
		customOptions,
1622
		"----------\n" + 
1623
		"1. ERROR in p\\Test.java (at line 2)\n" + 
1624
		"	import nullAnn.*;  // 1 \n" + 
1625
		"	       ^^^^^^^\n" + 
1626
		"The import nullAnn cannot be resolved\n" + 
1627
		"----------\n" + 
1628
		"2. ERROR in p\\Test.java (at line 6)\n" + 
1629
		"	void foo(@nullAnn.Nullable  Object o) {   // 2\n" + 
1630
		"	          ^^^^^^^\n" + 
1631
		"nullAnn cannot be resolved to a type\n" + 
1632
		"----------\n");
1633
}
1634
1635
public void test_default_nullness_002() {
1636
	Map customOptions = getCompilerOptions();
1637
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1638
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1639
	runNegativeTestWithLibs(
1640
		new String[] {
1641
			"X.java",
1642
			"import org.eclipse.jdt.annotation.*;\n" +
1643
			"public class X {\n" +
1644
			"    Object getObject(@Nullable Object o) {\n" +
1645
			"        return new Object();\n" +
1646
			"    }\n" +
1647
			"}\n",
1648
			"Y.java",
1649
			"import org.eclipse.jdt.annotation.*;\n" +
1650
			"public class Y extends X {\n" +
1651
			"    @Override\n" +
1652
			"    @Nullable Object getObject(Object o) {\n" + // complain illegal return redef and inherited annot is not repeated
1653
			"        return o;\n" +
1654
			"    }\n" +
1655
			"}\n",
1656
		},
1657
		customOptions,
1658
		// main error:
1659
		"----------\n" + 
1660
		"1. ERROR in Y.java (at line 4)\n" + 
1661
		"	@Nullable Object getObject(Object o) {\n" + 
1662
		"	^^^^^^^^^^^^^^^^\n" + 
1663
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1664
		"----------\n" +
1665
		// additional error:
1666
		"2. ERROR in Y.java (at line 4)\n" + 
1667
		"	@Nullable Object getObject(Object o) {\n" + 
1668
		"	                           ^^^^^^\n" + 
1669
		"Illegal redefinition of parameter o, inherited method from X declares this parameter as @Nullable\n" + 
1670
		"----------\n");
1671
}
1672
// package default is non-null
1673
public void test_default_nullness_003() {
1674
	Map customOptions = getCompilerOptions();
1675
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1676
	runNegativeTestWithLibs(
1677
		new String[] {
1678
	"p1/X.java",
1679
			"package p1;\n" +
1680
			"import org.eclipse.jdt.annotation.*;\n" +
1681
			"@NonNullByDefault\n" +
1682
			"public class X {\n" +
1683
			"    protected Object getObject(@Nullable Object o) {\n" +
1684
			"        return new Object();\n" +
1685
			"    }\n" +
1686
			"}\n",
1687
	"p2/package-info.java",
1688
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1689
			"package p2;\n",
1690
	"p2/Y.java",
1691
			"package p2;\n" +
1692
			"import org.eclipse.jdt.annotation.*;\n" +
1693
			"public class Y extends p1.X {\n" +
1694
			"    @Override\n" +
1695
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" +
1696
			"        bar(o);\n" +
1697
			"        return o;\n" +
1698
			"    }\n" +
1699
			"	 void bar(Object o2) { }\n" + // parameter is nonnull per package default
1700
			"}\n"
1701
		},
1702
		customOptions,
1703
		"----------\n" + 
1704
		"1. ERROR in p2\\Y.java (at line 5)\n" + 
1705
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" + 
1706
		"	          ^^^^^^^^^^^^^^^^\n" + 
1707
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1708
		"----------\n" + 
1709
		"2. ERROR in p2\\Y.java (at line 6)\n" + 
1710
		"	bar(o);\n" + 
1711
		"	    ^\n" + 
1712
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1713
		"----------\n");
1714
}
1715
// package level default is consumed from package-info.class
1716
public void test_default_nullness_003a() {
1717
	Map customOptions = getCompilerOptions();
1718
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1719
	runConformTestWithLibs(
1720
		new String[] {
1721
	"p1/X.java",
1722
			"package p1;\n" +
1723
			"import org.eclipse.jdt.annotation.*;\n" +
1724
			"@NonNullByDefault\n" +
1725
			"public class X {\n" +
1726
			"    protected Object getObject(@Nullable Object o) {\n" +
1727
			"        return new Object();\n" +
1728
			"    }\n" +
1729
			"	 protected void bar(Object o2) { }\n" + // parameter is nonnull per type default
1730
			"}\n",
1731
	"p2/package-info.java",
1732
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1733
			"package p2;\n",
1734
			},
1735
			customOptions,
1736
			"");
1737
	// check if default is visible from package-info.class.
1738
	runNegativeTestWithLibs(
1739
		false, // don't flush
1740
		new String[] {
1741
	"p2/Y.java",
1742
			"package p2;\n" +
1743
			"import org.eclipse.jdt.annotation.*;\n" +
1744
			"public class Y extends p1.X {\n" +
1745
			"    @Override\n" +
1746
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" + // can't override inherited default nonnull 
1747
			"        bar(o);\n" + // parameter is nonnull in super class's .class file
1748
			"        accept(o);\n" +
1749
			"        return o;\n" +
1750
			"    }\n" +
1751
			"    void accept(Object a) {}\n" + // governed by package level default
1752
			"}\n"
1753
		},
1754
		customOptions,
1755
		"----------\n" + 
1756
		"1. ERROR in p2\\Y.java (at line 5)\n" + 
1757
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" + 
1758
		"	          ^^^^^^^^^^^^^^^^\n" + 
1759
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1760
		"----------\n" + 
1761
		"2. ERROR in p2\\Y.java (at line 6)\n" + 
1762
		"	bar(o);\n" + 
1763
		"	    ^\n" + 
1764
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1765
		"----------\n" + 
1766
		"3. ERROR in p2\\Y.java (at line 7)\n" + 
1767
		"	accept(o);\n" + 
1768
		"	       ^\n" + 
1769
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1770
		"----------\n");
1771
}
1772
// don't apply type-level default to non-reference type
1773
public void test_default_nullness_004() {
1774
	Map customOptions = getCompilerOptions();
1775
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1776
	runConformTestWithLibs(
1777
		new String[] {
1778
	"p1/X.java",
1779
			"package p1;\n" +
1780
			"import org.eclipse.jdt.annotation.*;\n" +
1781
			"@NonNullByDefault\n" +
1782
			"public class X {\n" +
1783
			"    protected Object getObject(boolean o) {\n" +
1784
			"        return new Object();\n" +
1785
			"    }\n" +
1786
			"}\n",
1787
	"p2/Y.java",
1788
			"package p2;\n" +
1789
			"import org.eclipse.jdt.annotation.*;\n" +
1790
			"public class Y extends p1.X {\n" +
1791
			"    @Override\n" +
1792
			"    protected @NonNull Object getObject(boolean o) {\n" +
1793
			"        return o ? this : new Object();\n" +
1794
			"    }\n" +
1795
			"}\n"
1796
		},
1797
		customOptions,
1798
		"");
1799
}
1800
// package default is non-null
1801
// see also Bug 354536 - compiling package-info.java still depends on the order of compilation units
1802
public void test_default_nullness_005() {
1803
	Map customOptions = getCompilerOptions();
1804
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1805
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1806
	runNegativeTestWithLibs(
1807
		new String[] {
1808
	"p1/X.java",
1809
			"package p1;\n" +
1810
			"public class X {\n" +
1811
			"    class Inner {" +
1812
			"        protected Object getObject(String s) {\n" +
1813
			"            return null;\n" +
1814
			"        }\n" +
1815
			"    }\n" +
1816
			"}\n",
1817
	"p1/package-info.java",
1818
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1819
			"package p1;\n",
1820
	CUSTOM_NONNULL_NAME,
1821
			CUSTOM_NONNULL_CONTENT
1822
		},
1823
		customOptions,
1824
		"----------\n" + 
1825
		"1. ERROR in p1\\X.java (at line 4)\n" + 
1826
		"	return null;\n" + 
1827
		"	       ^^^^\n" + 
1828
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1829
		"----------\n");
1830
}
1831
// package default is non-null, package-info.java read before the annotation type
1832
// compile order: beginToCompile(X.Inner) triggers reading of package-info.java before the annotation type was read
1833
public void test_default_nullness_006() {
1834
	Map customOptions = getCompilerOptions();
1835
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1836
	customOptions.put(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "org.foo.NonNull");
1837
	runNegativeTestWithLibs(
1838
		new String[] {
1839
	"p1/package-info.java",
1840
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1841
			"package p1;\n",
1842
	"p1/X.java",
1843
			"package p1;\n" +
1844
			"public class X {\n" +
1845
			"    class Inner {" +
1846
			"        protected Object getObject(String s) {\n" +
1847
			"            return null;\n" +
1848
			"        }\n" +
1849
			"    }\n" +
1850
			"}\n",
1851
	CUSTOM_NONNULL_NAME,
1852
			CUSTOM_NONNULL_CONTENT
1853
		},
1854
		customOptions,
1855
		"----------\n" + 
1856
		"1. ERROR in p1\\X.java (at line 4)\n" + 
1857
		"	return null;\n" + 
1858
		"	       ^^^^\n" + 
1859
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1860
		"----------\n");
1861
}
1862
// global default nonnull, but return may be null 
1863
public void test_default_nullness_007() {
1864
	Map customOptions = getCompilerOptions();
1865
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1866
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1867
	runNegativeTestWithLibs(
1868
		new String[] {
1869
			"X.java",
1870
			"import org.eclipse.jdt.annotation.*;\n" +
1871
			"public class X {\n" +
1872
			"    @Nullable Object dangerous() {\n" +
1873
			"        return null;\n" + 
1874
			"    }\n" +
1875
			"    Object broken() {\n" +
1876
			"        return dangerous();\n" +
1877
			"    }\n" +
1878
			"}\n",
1879
1880
		},
1881
		customOptions,
1882
		"----------\n" + 
1883
		"1. ERROR in X.java (at line 7)\n" + 
1884
		"	return dangerous();\n" + 
1885
		"	       ^^^^^^^^^^^\n" + 
1886
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1887
		"----------\n");
1888
}
1889
1890
// cancel type level default to comply with super specification
1891
public void test_default_nullness_008() {
1892
	Map customOptions = getCompilerOptions();
1893
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1894
	runConformTestWithLibs(
1895
		new String[] {
1896
	"p1/X.java",
1897
			"package p1;\n" +
1898
			"public class X {\n" +
1899
			"    protected Object getObject(Object o) {\n" +
1900
			"        return new Object();\n" +
1901
			"    }\n" +
1902
			"}\n",
1903
	"p2/Y.java",
1904
			"package p2;\n" +
1905
			"import org.eclipse.jdt.annotation.*;\n" +
1906
			"@NonNullByDefault\n" +
1907
			"public class Y extends p1.X {\n" +
1908
			"    @Override\n" +
1909
			"    @NonNullByDefault(false)\n" +
1910
			"    protected Object getObject(Object o) {\n" +
1911
			"        if (o.toString().length() == 0)\n" + // dereference without a warning
1912
			"	        return null;\n" + // return null without a warning
1913
			"        return o.toString();\n" +
1914
			"    }\n" +
1915
			"}\n"
1916
		},
1917
		customOptions,
1918
		"");
1919
}
1920
1921
// cancel outer type level default to comply with super specification
1922
public void test_default_nullness_009() {
1923
	Map customOptions = getCompilerOptions();
1924
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1925
	runNegativeTestWithLibs(
1926
		new String[] {
1927
	"p1/X.java",
1928
			"package p1;\n" +
1929
			"public class X {\n" +
1930
			"    protected Object getObject(Object o) {\n" +
1931
			"        return new Object();\n" +
1932
			"    }\n" +
1933
			"}\n",
1934
	"p2/Y.java",
1935
			"package p2;\n" +
1936
			"import org.eclipse.jdt.annotation.*;\n" +
1937
			"@NonNullByDefault\n" +
1938
			"public class Y { \n" +
1939
			"    @NonNullByDefault(false)\n" +
1940
			"    static class Z extends p1.X {\n" +
1941
			"        @Override\n" +
1942
			"        protected Object getObject(Object o) {\n" +
1943
			"            if (o.toString().length() == 0) {\n" +
1944
			"                o = null;\n" + // assign null without a warning
1945
			"                bar(o); // error: arg is declared @NonNull\n" +
1946
			"	             return null;\n" +
1947
			"            }\n" +
1948
			"            return o.toString();\n" +
1949
			"        }\n" +
1950
			"        String bar(@NonNull Object o) {\n" +
1951
			"            return getObject(o).toString();" +
1952
			"        }\n" +
1953
			"    }\n" +
1954
			"}\n"
1955
		},
1956
		customOptions,
1957
		"----------\n" +
1958
		"1. ERROR in p2\\Y.java (at line 11)\n" + 
1959
		"	bar(o); // error: arg is declared @NonNull\n" +
1960
		"	    ^\n" +
1961
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1962
		"----------\n");
1963
}
1964
// non-null declarations are redundant within a default scope.
1965
public void test_default_nullness_010() {
1966
	Map customOptions = getCompilerOptions();
1967
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1968
	runConformTestWithLibs(
1969
		new String[] {
1970
	"p2/Y.java",
1971
			"package p2;\n" +
1972
			"import org.eclipse.jdt.annotation.*;\n" +
1973
			"@NonNullByDefault\n" +
1974
			"public class Y {\n" +
1975
			"    protected @NonNull Object getObject(@NonNull Object o) {\n" +
1976
			"        return o;\n" +
1977
			"    }\n" +
1978
			"}\n"
1979
		},
1980
		customOptions,
1981
		"----------\n" + 
1982
		"1. WARNING in p2\\Y.java (at line 5)\n" + 
1983
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" + 
1984
		"	          ^^^^^^^^^^^^^^^\n" + 
1985
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1986
		"----------\n" + 
1987
		"2. WARNING in p2\\Y.java (at line 5)\n" + 
1988
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" + 
1989
		"	                                    ^^^^^^^^^^^^^^^^^\n" + 
1990
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1991
		"----------\n");
1992
}
1993
// a nonnull variable is dereferenced in a loop
1994
public void test_nonnull_var_in_constrol_structure_1() {
1995
	Map customOptions = getCompilerOptions();
1996
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
1997
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
1998
	runNegativeTestWithLibs(
1999
		new String[] {
2000
			"X.java",
2001
			"import org.eclipse.jdt.annotation.*;\n" +
2002
			"public class X {\n" +
2003
			"    void print4(@NonNull String s) {\n" +
2004
			"        for (int i=0; i<4; i++)\n" +
2005
			"             print(s);\n" + 
2006
			"    }\n" +
2007
			"    void print5(@Nullable String s) {\n" +
2008
			"        for (int i=0; i<5; i++)\n" +
2009
			"             print(s);\n" + 
2010
			"    }\n" +
2011
			"    void print6(boolean b) {\n" +
2012
			"        String s = b ? null : \"\";\n" +
2013
			"        for (int i=0; i<5; i++)\n" +
2014
			"             print(s);\n" + 
2015
			"    }\n" +
2016
			"    void print(@NonNull String s) {\n" +
2017
			"        System.out.print(s);\n" +
2018
			"    }\n" +
2019
			"}\n",
2020
2021
		},
2022
		customOptions,
2023
		"----------\n" + 
2024
		"1. WARNING in X.java (at line 3)\n" + 
2025
		"	void print4(@NonNull String s) {\n" + 
2026
		"	            ^^^^^^^^^^^^^^^^^\n" + 
2027
		"The nullness annotation is redundant with a default that applies to this location\n" + 
2028
		"----------\n" + 
2029
		"2. ERROR in X.java (at line 9)\n" + 
2030
		"	print(s);\n" + 
2031
		"	      ^\n" + 
2032
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2033
		"----------\n" + 
2034
		"3. ERROR in X.java (at line 14)\n" + 
2035
		"	print(s);\n" + 
2036
		"	      ^\n" + 
2037
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2038
		"----------\n" + 
2039
		"4. WARNING in X.java (at line 16)\n" + 
2040
		"	void print(@NonNull String s) {\n" + 
2041
		"	           ^^^^^^^^^^^^^^^^^\n" + 
2042
		"The nullness annotation is redundant with a default that applies to this location\n" + 
2043
		"----------\n");
2044
}
2045
// a nonnull variable is dereferenced in a finally block
2046
public void test_nonnull_var_in_constrol_structure_2() {
2047
	Map customOptions = getCompilerOptions();
2048
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2049
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2050
	runNegativeTestWithLibs(
2051
		new String[] {
2052
			"X.java",
2053
			"import org.eclipse.jdt.annotation.*;\n" +
2054
			"public class X {\n" +
2055
			"    void print4(String s) {\n" +
2056
			"        try { /*empty*/ } finally {\n" +
2057
			"             print(s);\n" +
2058
			"        }\n" + 
2059
			"    }\n" +
2060
			"    void print5(@Nullable String s) {\n" +
2061
			"        try { /*empty*/ } finally {\n" +
2062
			"             print(s);\n" +
2063
			"        }\n" + 
2064
			"    }\n" +
2065
			"    void print6(boolean b) {\n" +
2066
			"        String s = b ? null : \"\";\n" +
2067
			"        try { /*empty*/ } finally {\n" +
2068
			"             print(s);\n" +
2069
			"        }\n" + 
2070
			"    }\n" +
2071
			"    void print(String s) {\n" +
2072
			"        System.out.print(s);\n" +
2073
			"    }\n" +
2074
			"}\n",
2075
2076
		},
2077
		customOptions,
2078
		"----------\n" + 
2079
		"1. ERROR in X.java (at line 10)\n" + 
2080
		"	print(s);\n" + 
2081
		"	      ^\n" + 
2082
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2083
		"----------\n" + 
2084
		"2. ERROR in X.java (at line 16)\n" + 
2085
		"	print(s);\n" + 
2086
		"	      ^\n" + 
2087
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2088
		"----------\n");
2089
}
2090
// a nonnull variable is dereferenced in a finally block inside a loop
2091
public void test_nonnull_var_in_constrol_structure_3() {
2092
	Map customOptions = getCompilerOptions();
2093
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2094
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2095
	customOptions.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.IGNORE);
2096
	runNegativeTestWithLibs(
2097
		new String[] {
2098
			"X.java",
2099
			"import org.eclipse.jdt.annotation.*;\n" +
2100
			"public class X {\n" +
2101
			"    void print4(@NonNull String s) {\n" +
2102
			"        for (int i=0; i<4; i++)\n" +
2103
			"            try { /*empty*/ } finally {\n" +
2104
			"                 print(s);\n" +
2105
			"            }\n" + 
2106
			"    }\n" +
2107
			"    void print5(@Nullable String s) {\n" +
2108
			"        for (int i=0; i<5; i++)\n" +
2109
			"            try { /*empty*/ } finally {\n" +
2110
			"                 print(s);\n" +
2111
			"            }\n" + 
2112
			"    }\n" +
2113
			"    void print6(boolean b) {\n" +
2114
			"        String s = b ? null : \"\";\n" +
2115
			"        for (int i=0; i<4; i++)\n" +
2116
			"            try { /*empty*/ } finally {\n" +
2117
			"                 print(s);\n" +
2118
			"            }\n" + 
2119
			"    }\n" +
2120
			"    void print(@NonNull String s) {\n" +
2121
			"        System.out.print(s);\n" +
2122
			"    }\n" +
2123
			"}\n",
2124
2125
		},
2126
		customOptions,
2127
		"----------\n" + 
2128
		"1. ERROR in X.java (at line 12)\n" + 
2129
		"	print(s);\n" + 
2130
		"	      ^\n" + 
2131
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2132
		"----------\n" + 
2133
		"2. ERROR in X.java (at line 19)\n" + 
2134
		"	print(s);\n" + 
2135
		"	      ^\n" + 
2136
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2137
		"----------\n");
2138
}
2139
// a nonnull variable is dereferenced method of a nested type
2140
public void test_nesting_1() {
2141
	Map customOptions = getCompilerOptions();
2142
//	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR);
2143
	customOptions.put(JavaCore.COMPILER_NONNULL_IS_DEFAULT, JavaCore.ENABLED);
2144
	runNegativeTestWithLibs(
2145
		new String[] {
2146
			"X.java",
2147
			"import org.eclipse.jdt.annotation.*;\n" +
2148
			"@NonNullByDefault\n" +
2149
			"public class X {\n" +
2150
			"    void print4(final String s1) {\n" +
2151
			"        for (int i=0; i<3; i++)\n" +
2152
			"            new Runnable() {\n" +
2153
			"                public void run() {\n" +
2154
			"                     print(s1);\n" +
2155
			"                }\n" +
2156
			"            }.run();\n" + 
2157
			"    }\n" +
2158
			"    void print8(final @Nullable String s2) {\n" +
2159
			"        for (int i=0; i<3; i++)\n" +
2160
			"            new Runnable() {\n" +
2161
			"                public void run() {\n" +
2162
			"                     print(s2);\n" +
2163
			"                }\n" +
2164
			"            }.run();\n" + 
2165
			"    }\n" +
2166
			"    void print16(boolean b) {\n" +
2167
			"        final String s3 = b ? null : \"\";\n" +
2168
			"        for (int i=0; i<3; i++)\n" +
2169
			"            new Runnable() {\n" +
2170
			"                public void run() {\n" +
2171
			"                     @NonNull String s3R = s3;\n" +
2172
			"                }\n" +
2173
			"            }.run();\n" + 
2174
			"    }\n" +
2175
			"    void print(String s) {\n" +
2176
			"        System.out.print(s);\n" +
2177
			"    }\n" +
2178
			"}\n",
2179
2180
		},
2181
		customOptions,
2182
		"----------\n" + 
2183
		"1. ERROR in X.java (at line 16)\n" + 
2184
		"	print(s2);\n" + 
2185
		"	      ^^\n" + 
2186
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2187
		"----------\n" + 
2188
		"2. ERROR in X.java (at line 25)\n" + 
2189
		"	@NonNull String s3R = s3;\n" + 
2190
		"	                      ^^\n" + 
2191
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2192
		"----------\n");
2193
}
2194
// Test a regression incurred to the OT/J based implementation
2195
// by the fix in Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
2196
public void test_constructor_with_nested_class() {
2197
	runConformTest(
2198
		new String[] {
2199
			"X.java",
2200
			"public class X {\n" +
2201
			"    final Object o1;\n" +
2202
			"    final Object o2;\n" +
2203
			"    public X() {\n" +
2204
			"         this.o1 = new Object() {\n" +
2205
			"             public String toString() { return \"O1\"; }\n" +
2206
			"         };\n" +
2207
			"         this.o2 = new Object();" +
2208
			"    }\n" +
2209
			"}\n"
2210
		},
2211
		"");
2212
}
2213
}
(-)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 (+410 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
	public void testMissingAnnotation3() throws CoreException {
237
    	try {
238
			// Resources creation
239
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
240
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
241
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "invalid");
242
	
243
			this.createFolder("/P/p1");
244
			String c1SourceString =	
245
				"package p1;\n" +
246
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
247
				"public class C1 {\n" +
248
				"	 public String foo(Object arg) {\n" +
249
				"		return arg == null ? \"\" : arg.toString();\n" +
250
				"	 }\n" +
251
				"}\n";
252
			this.createFile(
253
				"/P/p1/C1.java",
254
	    			c1SourceString);
255
256
			this.problemRequestor.initialize(c1SourceString.toCharArray());
257
			
258
			final ICompilationUnit unit = getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
259
			assertProblems("Unexpected problems", 
260
					"----------\n" + 
261
					"1. ERROR in /P/p1/C1.java (at line 0)\n" + 
262
					"	package p1;\n" + 
263
					"	^\n" + 
264
					"Cannot use the unqualified name \'invalid\' as an annotation name for null specification\n" + 
265
					"----------\n");
266
267
			ASTParser parser = ASTParser.newParser(AST.JLS4);
268
			parser.setProject(p);
269
			parser.setResolveBindings(true);
270
			parser.setSource(unit);
271
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
272
			assertNotNull("ast should not be null", ast);
273
			this.problemRequestor.reset();
274
			this.problemRequestor.beginReporting();
275
			IProblem[] problems = ast.getProblems();
276
			for (int i=0; i<problems.length; i++)
277
				this.problemRequestor.acceptProblem(problems[i]);
278
			assertProblems("Unexpected problems (2)", 
279
					"----------\n" + 
280
					"1. ERROR in /P/p1/C1.java (at line 0)\n" + 
281
					"	package p1;\n" + 
282
					"	^\n" + 
283
					"Cannot use the unqualified name \'invalid\' as an annotation name for null specification\n" + 
284
					"----------\n");
285
    	} finally {
286
    		deleteProject("P");
287
    	}
288
	}
289
290
	// initialization of null annotations is triggered from package-info.java: illegal simple name
291
	public void testMissingAnnotation4() throws CoreException {
292
    	try {
293
			// Resources creation
294
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
295
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
296
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "invalid");
297
	
298
			this.createFolder("/P/p1");
299
			String piSourceString =	
300
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
301
				"package p1;\n";
302
			this.createFile(
303
				"/P/p1/package-info.java",
304
	    			piSourceString);
305
306
			this.problemRequestor.initialize(piSourceString.toCharArray());
307
			
308
			// Challenge CompilationUnitProblemFinder:
309
			final ICompilationUnit unit = getCompilationUnit("/P/p1/package-info.java").getWorkingCopy(this.wcOwner, null);
310
			String expectedError = "----------\n" + 
311
								   "1. ERROR in /P/p1/package-info.java (at line 0)\n" + 
312
								   "	@org.eclipse.jdt.annotation.NonNullByDefault\n" + 
313
								   "	^\n" + 
314
								   "Cannot use the unqualified name \'invalid\' as an annotation name for null specification\n" + 
315
								   "----------\n";
316
			assertProblems("Unexpected problems from CompilationUnitProblemFinder", expectedError);
317
318
			// Challenge JavaBuilder:
319
			p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
320
			IMarker[] markers = p.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
321
			assertMarkers("Unexpected markers", 
322
					"Cannot use the unqualified name 'invalid' as an annotation name for null specification", 
323
					markers);
324
			assertEquals("Unexpected marker path", "/P", markers[0].getResource().getFullPath().toString());
325
326
			// Challenge CompilationUnitResolver:
327
			ASTParser parser = ASTParser.newParser(AST.JLS4);
328
			parser.setProject(p);
329
			parser.setResolveBindings(true);
330
			parser.setSource(unit);
331
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
332
			assertNotNull("ast should not be null", ast);
333
			this.problemRequestor.reset();
334
			this.problemRequestor.beginReporting();
335
			IProblem[] problems = ast.getProblems();
336
			for (int i=0; i<problems.length; i++)
337
				this.problemRequestor.acceptProblem(problems[i]);
338
			assertProblems("Unexpected problems from CompilationUnitResolver", expectedError);
339
    	} finally {
340
    		deleteProject("P");
341
    	}
342
	}
343
344
	// initialization of null annotations is 
345
	// - triggered from resolveTypesFor(MethodBinding)
346
	// - default is defined in package-info.java:
347
	// must detect missing non-null annotation and report against the project
348
	public void testMissingAnnotation5() throws CoreException, InterruptedException {
349
    	try {
350
			// Resources creation
351
			IJavaProject p = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB", this.ANNOTATION_LIB}, "bin", "1.5");
352
			p.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
353
			p.setOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, "pack.Missing");
354
	
355
			this.createFolder("/P/p1");
356
			String piSourceString =	
357
				"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
358
				"package p1;\n";
359
			this.createFile("/P/p1/package-info.java", piSourceString);
360
			
361
			String c1SourceString = 
362
				"package p1;\n" +
363
				"public class C1 {\n" +
364
				"    String foo(String arg) { return arg; }\n" +
365
				"}\n";
366
			this.createFile("/P/p1/C1.java", c1SourceString);
367
368
			this.problemRequestor.initialize(piSourceString.toCharArray());
369
			
370
			// Challenge CompilationUnitProblemFinder:
371
			assertNoProblem(piSourceString.toCharArray(), getCompilationUnit("/P/p1/package-info.java"));
372
			
373
			this.problemRequestor.initialize(c1SourceString.toCharArray());
374
			
375
			// Challenge CompilationUnitProblemFinder:
376
			ICompilationUnit unit = getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
377
			String expectedError = "----------\n" + 
378
								   "1. ERROR in /P/p1/C1.java (at line 1)\n" + 
379
								   "	package p1;\n" + 
380
								   "	^\n" + 
381
								   "Buildpath problem: the type pack.Missing, which is configured as a null annotation type, cannot be resolved\n" + 
382
								   "----------\n";
383
			assertProblems("Unexpected problems", expectedError);
384
385
			// Challenge JavaBuilder:
386
			p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
387
			IMarker[] markers = p.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
388
			assertMarkers("Unexpected markers", 
389
					"Buildpath problem: the type pack.Missing, which is configured as a null annotation type, cannot be resolved", 
390
					markers);
391
			assertEquals("Unexpected marker path", "/P", markers[0].getResource().getFullPath().toString());
392
393
			// Challenge CompilationUnitResolver:
394
			ASTParser parser = ASTParser.newParser(AST.JLS4);
395
			parser.setProject(p);
396
			parser.setResolveBindings(true);
397
			parser.setSource(unit);
398
			CompilationUnit ast = (CompilationUnit) parser.createAST(null);
399
			assertNotNull("ast should not be null", ast);
400
			this.problemRequestor.reset();
401
			this.problemRequestor.beginReporting();
402
			IProblem[] problems = ast.getProblems();
403
			for (int i=0; i<problems.length; i++)
404
				this.problemRequestor.acceptProblem(problems[i]);
405
			assertProblems("Unexpected problems (2)", expectedError);
406
    	} finally {
407
    		deleteProject("P");
408
    	}
409
	}
410
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java (+48 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
1414
	/** @since 3.8 */
1428
	/** @since 3.8 */
1415
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1429
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1416
	/**
1430
	/**
1431
	 * Errors/warnings from annotation based null analysis
1432
	 */
1433
	/** @since 3.8 */
1434
	int RequiredNonNullButProvidedNull = TypeRelated + 910;
1435
	/** @since 3.8 */
1436
	int RequiredNonNullButProvidedPotentialNull = TypeRelated + 911;
1437
	/** @since 3.8 */
1438
	int RequiredNonNullButProvidedUnknown = TypeRelated + 912;
1439
	/** @since 3.8 */
1440
	int MissingNullAnnotationType = ImportRelated + 913;
1441
	/** @since 3.8 */
1442
	int NullAnnotationNameMustBeQualified = Internal + 914;
1443
	/** @since 3.8 */
1444
	int IllegalReturnNullityRedefinition = MethodRelated + 915;
1445
	/** @since 3.8 */
1446
	int IllegalRedefinitionToNonNullParameter = MethodRelated + 916;
1447
	/** @since 3.8 */
1448
	int IllegalDefinitionToNonNullParameter = MethodRelated + 917;
1449
	/** @since 3.8 */
1450
	int ParameterLackingNonNullAnnotation = MethodRelated + 918;
1451
	/** @since 3.8 */
1452
	int ParameterLackingNullableAnnotation = MethodRelated + 919;
1453
	/** @since 3.8 */
1454
	int PotentialNullMessageSendReference = Internal + 920;
1455
	/** @since 3.8 */
1456
	int RedundantNullCheckOnNonNullMessageSend = Internal + 921;
1457
	/** @since 3.8 */
1458
	int CannotImplementIncompatibleNullness = Internal + 922;
1459
	/** @since 3.8 */
1460
	int RedundantNullAnnotation = MethodRelated + 923;
1461
	/** @since 3.8 */	
1462
	int IllegalAnnotationForBaseType = TypeRelated + 924;
1463
1464
	/**
1417
	 * External problems -- These are problems defined by other plugins
1465
	 * External problems -- These are problems defined by other plugins
1418
	 */
1466
	 */
1419
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 (+88 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 138-143 Link Here
138
							bindingIndex++;
197
							bindingIndex++;
139
						}
198
						}
140
					}
199
					}
200
				}
201
			}
202
		}
203
	}
204
205
	void analyseArgumentNullity(FlowInfo info) {
206
		if (this.arguments != null && this.binding.parameterNonNullness != null) {
207
			for (int i = 0, count = this.arguments.length; i < count; i++) {
208
				// leverage null-info from parameter annotations:
209
				Boolean nonNullNess = this.binding.parameterNonNullness[i];
210
				if (nonNullNess != null) {
211
					if (nonNullNess.booleanValue())
212
						info.markAsDefinitelyNonNull(this.arguments[i].binding);
213
					else
214
						info.markPotentiallyNullBit(this.arguments[i].binding);
141
				}
215
				}
142
			}
216
			}
143
		}
217
		}
Lines 415-420 Link Here
415
			bindThrownExceptions();
489
			bindThrownExceptions();
416
			resolveJavadoc();
490
			resolveJavadoc();
417
			resolveAnnotations(this.scope, this.annotations, this.binding);
491
			resolveAnnotations(this.scope, this.annotations, this.binding);
492
			validateAnnotations();
418
			resolveStatements();
493
			resolveStatements();
419
			// check @Deprecated annotation presence
494
			// check @Deprecated annotation presence
420
			if (this.binding != null
495
			if (this.binding != null
Lines 478-481 Link Here
478
	public TypeParameter[] typeParameters() {
553
	public TypeParameter[] typeParameters() {
479
	    return null;
554
	    return null;
480
	}
555
	}
556
557
	void validateAnnotations() {
558
		// null annotations on parameters?
559
		if (this.binding != null && this.binding.parameterNonNullness != null) {
560
			for (int i=0; i<this.binding.parameters.length; i++) {
561
				if (this.binding.parameterNonNullness[i] != null) {
562
					long nullAnnotationTagBit =  this.binding.parameterNonNullness[i].booleanValue()
563
							? TagBits.AnnotationNonNull : TagBits.AnnotationNullable;
564
					this.scope.validateNullAnnotation(nullAnnotationTagBit, this.arguments[i].type, this.arguments[i].annotations);
565
				}
566
			}
567
		}
568
	}
481
}
569
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (+2 lines)
Lines 11-16 Link Here
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 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 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 51-73 Link Here
51
				}
70
				}
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 (-1 / +2 lines)
Lines 13-18 Link Here
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 (-1 / +12 lines)
Lines 10-15 Link Here
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-121 Link Here
113
			}
114
			}
114
		}
115
		}
115
116
116
		// tag parameters as being set
117
		if (this.arguments != null) {
117
		if (this.arguments != null) {
118
			for (int i = 0, count = this.arguments.length; i < count; i++) {
118
			for (int i = 0, count = this.arguments.length; i < count; i++) {
119
				if (this.binding.parameterNonNullness != null) {
120
					// leverage null-info from parameter annotations:
121
					Boolean nonNullNess = this.binding.parameterNonNullness[i];
122
					if (nonNullNess != null) {
123
						if (nonNullNess.booleanValue())
124
							flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
125
						else
126
							flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
127
					}
128
				}
129
				// tag parameters as being set
119
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
130
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
120
			}
131
			}
121
		}
132
		}
(-)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 (-1 / +3 lines)
Lines 12-17 Link Here
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 (-2 / +21 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-87 Link Here
79
					this.scope,
81
					this.scope,
80
					FlowInfo.DEAD_END);
82
					FlowInfo.DEAD_END);
81
83
82
			// tag parameters as being set
83
			if (this.arguments != null) {
84
			if (this.arguments != null) {
84
				for (int i = 0, count = this.arguments.length; i < count; i++) {
85
				for (int i = 0, count = this.arguments.length; i < count; i++) {
86
					if (this.binding.parameterNonNullness != null) {
87
						// leverage null-info from parameter annotations:
88
						Boolean nonNullNess = this.binding.parameterNonNullness[i];
89
						if (nonNullNess != null) {
90
							if (nonNullNess.booleanValue())
91
								flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
92
							else
93
								flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
94
						}
95
					}
96
					// tag parameters as being set:
85
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
97
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
86
					// if this method uses a type parameter declared by the declaring class,
98
					// 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
99
					// it can't be static. https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
Lines 307-310 Link Here
307
	public TypeParameter[] typeParameters() {
319
	public TypeParameter[] typeParameters() {
308
	    return this.typeParameters;
320
	    return this.typeParameters;
309
	}
321
	}
322
	
323
	void validateAnnotations() {
324
		super.validateAnnotations();
325
		// null-annotations on the return type?
326
		if (this.binding != null)
327
			this.scope.validateNullAnnotation(this.binding.tagBits, this.returnType, this.annotations);
328
	}
310
}
329
}
(-)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 (+20 lines)
Lines 11-16 Link Here
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 (-2 / +30 lines)
Lines 10-15 Link Here
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 (-1 / +51 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 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 / +99 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-21 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;
Lines 383-388 Link Here
383
		}
386
		}
384
		if (this.environment.globalOptions.storeAnnotations)
387
		if (this.environment.globalOptions.storeAnnotations)
385
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
388
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
389
		
390
		scanTypeForNullAnnotation(binaryType);
386
	} finally {
391
	} finally {
387
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
392
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
388
		if (this.fields == null)
393
		if (this.fields == null)
Lines 589-594 Link Here
589
	// fixup the declaring element of the type variable
594
	// fixup the declaring element of the type variable
590
	for (int i = 0, length = typeVars.length; i < length; i++)
595
	for (int i = 0, length = typeVars.length; i < length; i++)
591
		typeVars[i].declaringElement = result;
596
		typeVars[i].declaringElement = result;
597
	
598
	scanMethodForNullAnnotation(method, result);
599
	
592
	return result;
600
	return result;
593
}
601
}
594
602
Lines 1142-1147 Link Here
1142
	}
1150
	}
1143
	return this.storedAnnotations;
1151
	return this.storedAnnotations;
1144
}
1152
}
1153
void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) {
1154
	char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
1155
	char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
1156
	if (nullableAnnotationName == null || nonNullAnnotationName == null)
1157
		return; // not configured to use null annotations
1158
1159
	// return:
1160
	IBinaryAnnotation[] annotations = method.getAnnotations();
1161
	if (annotations != null) {
1162
		for (int i = 0; i < annotations.length; i++) {
1163
			char[] annotationTypeName = annotations[i].getTypeName();
1164
			if (annotationTypeName[0] != 'L')
1165
				continue;
1166
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1167
			if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1168
				methodBinding.tagBits |= TagBits.AnnotationNonNull;
1169
				break;
1170
			}
1171
			if (CharOperation.equals(typeName, nullableAnnotationName)) {
1172
				methodBinding.tagBits |= TagBits.AnnotationNullable;
1173
				break;
1174
			}
1175
		}
1176
	}
1177
1178
	// parameters:
1179
	TypeBinding[] parameters = methodBinding.parameters;
1180
	for (int j = 0; j < parameters.length; j++) {
1181
		IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j); 
1182
		if (paramAnnotations != null) {
1183
			for (int i = 0; i < paramAnnotations.length; i++) {
1184
				char[] annotationTypeName = paramAnnotations[i].getTypeName();
1185
				if (annotationTypeName[0] != 'L')
1186
					continue;
1187
				char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1188
				if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1189
					if (methodBinding.parameterNonNullness == null)
1190
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1191
					methodBinding.parameterNonNullness[j] = Boolean.TRUE;
1192
					break;
1193
				} else if (CharOperation.equals(typeName, nullableAnnotationName)) {
1194
					if (methodBinding.parameterNonNullness == null)
1195
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1196
					methodBinding.parameterNonNullness[j] = Boolean.FALSE;
1197
					break;
1198
				}
1199
			}
1200
		}
1201
	}
1202
}
1203
void scanTypeForNullAnnotation(IBinaryType binaryType) {
1204
	char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
1205
	if (nonNullByDefaultAnnotationName == null)
1206
		return; // not configured to use null annotations
1207
1208
	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
1209
	if (annotations != null) {
1210
		long annotationBit = 0L;
1211
		TypeBinding defaultNullness = null;
1212
		for (int i = 0; i < annotations.length; i++) {
1213
			char[] annotationTypeName = annotations[i].getTypeName();
1214
			if (annotationTypeName[0] != 'L')
1215
				continue;
1216
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1217
			if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
1218
				IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
1219
				if (elementValuePairs != null && elementValuePairs.length == 1) {
1220
					Object value = elementValuePairs[0].getValue();
1221
					if (value instanceof BooleanConstant
1222
						&& !((BooleanConstant)value).booleanValue()) 
1223
					{
1224
						// parameter is 'false': this means we cancel defaults from outer scopes:
1225
						annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
1226
						defaultNullness = ReferenceBinding.NULL_UNSPECIFIED;
1227
						break;
1228
					}
1229
				}
1230
				annotationBit = TagBits.AnnotationNonNullByDefault;
1231
				defaultNullness = this.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, false/*resolve*/);
1232
				break;
1233
			}
1234
		}
1235
		if (annotationBit != 0L) {
1236
			this.tagBits |= annotationBit;
1237
			if (CharOperation.equals(this.sourceName(), TypeConstants.PACKAGE_INFO_NAME))
1238
				this.getPackage().nullnessDefaultAnnotation = defaultNullness;
1239
		}
1240
	}
1241
}
1242
1145
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1243
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1146
*
1244
*
1147
* NOTE: superclass of a binary type is resolved when needed
1245
* NOTE: superclass of a binary type is resolved when needed
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java (-5 / +8 lines)
Lines 10-15 Link Here
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 / +106 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
	private char[][][] nullAnnotationPackageNames = null; 	// package parts of globalOptions.{nullableAnnotationName,nonNullAnnotationName,nonNullByDefaultAnnotationName}
82
	private char[][] nullAnnotationSimpleNames = null;	 	// type parts of    globalOptions.{nullableAnnotationName,nonNullAnnotationName,nonNullByDefaultAnnotationName}
83
79
	final static int BUILD_FIELDS_AND_METHODS = 4;
84
	final static int BUILD_FIELDS_AND_METHODS = 4;
80
	final static int BUILD_TYPE_HIERARCHY = 1;
85
	final static int BUILD_TYPE_HIERARCHY = 1;
81
	final static int CHECK_AND_SET_IMPORTS = 2;
86
	final static int CHECK_AND_SET_IMPORTS = 2;
Lines 83-88 Link Here
83
88
84
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
89
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
85
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
90
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
91
86
92
87
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
93
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
88
	this.typeRequestor = typeRequestor;
94
	this.typeRequestor = typeRequestor;
Lines 1073-1078 Link Here
1073
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1079
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1074
}
1080
}
1075
1081
1082
public char[][] getNullableAnnotationName() {
1083
	return this.globalOptions.nullableAnnotationName;
1084
}
1085
1086
public char[][] getNonNullAnnotationName() {
1087
	return this.globalOptions.nonNullAnnotationName;
1088
}
1089
1090
public char[][] getNonNullByDefaultAnnotationName() {
1091
	return this.globalOptions.nonNullByDefaultAnnotationName;
1092
}
1093
1094
/**
1095
 * Answer the type binding representing the null-annotation identified by the given tag bits.
1096
 * @param annotationTagBit tag bits potentially denoting a null-annotation
1097
 * @param resolve should the resulting type binding be resolved?
1098
 * @return the corresponding annotation type binding 
1099
 * 		or <code>null</code> if no annotation bits are contained in the given tag bits.
1100
 */
1101
public TypeBinding getNullAnnotationBinding(long annotationTagBit, boolean resolve) {
1102
	char[][] name = null;
1103
	if (annotationTagBit == TagBits.AnnotationNonNull)
1104
		name = getNonNullAnnotationName();
1105
	else if (annotationTagBit == TagBits.AnnotationNullable)
1106
		name = getNullableAnnotationName();
1107
	else
1108
		return null;
1109
	if (resolve)
1110
		return getType(name);
1111
	else
1112
		return getTypeFromCompoundName(name, false, false);
1113
}
1114
1115
/**
1116
 * Inspect the given tag bits and answer a corresponding null annotation type binding
1117
 * @param defaultTagBit tag bits representing the default applicable at the current code location
1118
 * @param resolve should the resulting type binding be resolved?
1119
 * @return the corresponding concrete annotation type binding (<code>@NonNull</code> or <code>@Nullable</code>) 
1120
 * 		or <code>null</code> if no bits of a default-annotation are contained in the given tag bits.
1121
 */
1122
public TypeBinding getNullAnnotationBindingFromDefault(long defaultTagBit, boolean resolve) {
1123
	if ((defaultTagBit & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
1124
		return ReferenceBinding.NULL_UNSPECIFIED;
1125
	if ((defaultTagBit & TagBits.AnnotationNonNullByDefault) != 0)
1126
		return getNullAnnotationBinding(TagBits.AnnotationNonNull, resolve);
1127
	return null;
1128
}
1129
1130
/** answer the simple names of annotation types nullable/nonnull/nonnullbydefault if their package is packageName. */
1131
char[][] getNullAnnotationNames(char[][] packageName) {
1132
	if (this.nullAnnotationPackageNames == null) {
1133
		// fetch and split names from globalOptions to local fields nullAnnotationPackageNames & nullAnnotationsSimpleNames:
1134
		this.nullAnnotationPackageNames = new char[3][][];
1135
		this.nullAnnotationSimpleNames = new char[3][];
1136
		char[][][] compoundNames = new char[][][] {getNullableAnnotationName(), getNonNullAnnotationName(), getNonNullByDefaultAnnotationName() };
1137
		for (int i=0; i<3; i++) {
1138
			int len = compoundNames[i].length;
1139
			if (len < 2) {
1140
				this.problemReporter.nullAnnotationNameMustBeQualified(compoundNames[i], this.unitBeingCompleted);
1141
				// the above error may or may not throw AbortCompilation (is problemReporter.referenceContext set?)
1142
				continue;
1143
			}
1144
			this.nullAnnotationPackageNames[i] = CharOperation.subarray(compoundNames[i], 0, len-1);
1145
			this.nullAnnotationSimpleNames[i] = compoundNames[i][len-1];
1146
		}
1147
	}
1148
	// search in local storage:
1149
	boolean found = false;
1150
	char[][] simpleNames = new char[3][];
1151
	for (int i=0; i<3; i++) {
1152
		if (CharOperation.equals(packageName, this.nullAnnotationPackageNames[i])) {
1153
			simpleNames[i] = this.nullAnnotationSimpleNames[i];
1154
			found = true;
1155
		}
1156
	}
1157
	if (found)
1158
		return simpleNames;
1159
	else
1160
		return null;
1161
}
1162
1163
TypeBinding getNullAnnotationResolved(TypeBinding nullAnnotation, Scope scope) {
1164
	// avoid unspecific error "The type in.valid cannot be resolved. It is indirectly referenced from required .class files"
1165
	boolean tolerateMissing = this.mayTolerateMissingType;
1166
	this.mayTolerateMissingType = true;
1167
	try {
1168
		nullAnnotation = BinaryTypeBinding.resolveType(nullAnnotation, this, false);
1169
	} finally {
1170
		this.mayTolerateMissingType = tolerateMissing;
1171
	}
1172
	if (nullAnnotation instanceof MissingTypeBinding) {
1173
		// convert error into a specific one:
1174
		scope.problemReporter().missingNullAnnotationType(((MissingTypeBinding)nullAnnotation).compoundName);
1175
		return null;
1176
	}
1177
	return nullAnnotation;
1178
}
1179
1076
/* Answer the top level package named name if it exists in the cache.
1180
/* 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
1181
* Answer theNotFoundPackage if it could not be resolved the first time
1078
* it was looked up, otherwise answer null.
1182
* it was looked up, otherwise answer null.
Lines 1454-1459 Link Here
1454
	this.unitBeingCompleted = null; // in case AbortException occurred
1558
	this.unitBeingCompleted = null; // in case AbortException occurred
1455
1559
1456
	this.classFilePool.reset();
1560
	this.classFilePool.reset();
1561
1457
	// name environment has a longer life cycle, and must be reset in
1562
	// name environment has a longer life cycle, and must be reset in
1458
	// the code which created it.
1563
	// the code which created it.
1459
}
1564
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java (+39 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 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 / +47 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
	// if this package contains configured null-annotations, store their simple names here:
28
	protected char[] nullableName = null;
29
	protected char[] nonNullName = null;
30
	protected char[] nonNullByDefaultName = null;
31
	// annotation type binding representing the default that has been defined for this package (using @NonNullByDefault)
32
	protected TypeBinding nullnessDefaultAnnotation;
33
25
protected PackageBinding() {
34
protected PackageBinding() {
26
	// for creating problem package
35
	// for creating problem package
27
}
36
}
Lines 36-41 Link Here
36
	this.environment = environment;
45
	this.environment = environment;
37
	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
46
	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
47
	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
48
	if (compoundName != CharOperation.NO_CHAR_CHAR && environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
49
		initNullAnnotationPackage();
39
}
50
}
40
51
41
public PackageBinding(LookupEnvironment environment) {
52
public PackageBinding(LookupEnvironment environment) {
Lines 58-63 Link Here
58
	if (this.knownTypes == null)
69
	if (this.knownTypes == null)
59
		this.knownTypes = new HashtableOfType(25);
70
		this.knownTypes = new HashtableOfType(25);
60
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
71
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
72
	if (this.nullableName != null || this.nonNullName != null || this.nonNullByDefaultName != null)
73
		setupNullAnnotationType(element);
61
}
74
}
62
75
63
void clearMissingTagBit() {
76
void clearMissingTagBit() {
Lines 204-209 Link Here
204
217
205
	return null;
218
	return null;
206
}
219
}
220
221
private void initNullAnnotationPackage() {
222
	char[][] simpleAnnotNames = this.environment.getNullAnnotationNames(this.compoundName);
223
	if (simpleAnnotNames == null)
224
		return;
225
	if (simpleAnnotNames[0] != null)
226
		this.nullableName = simpleAnnotNames[0];
227
	if (simpleAnnotNames[1] != null)
228
		this.nonNullName = simpleAnnotNames[1];
229
	if (simpleAnnotNames[2] != null)
230
		this.nonNullByDefaultName = simpleAnnotNames[2];
231
}
232
207
public final boolean isViewedAsDeprecated() {
233
public final boolean isViewedAsDeprecated() {
208
	if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
234
	if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
209
		this.tagBits |= TagBits.DeprecatedAnnotationResolved;
235
		this.tagBits |= TagBits.DeprecatedAnnotationResolved;
Lines 230-235 Link Here
230
	return ProblemReasons.NoError;
256
	return ProblemReasons.NoError;
231
}
257
}
232
258
259
void setupNullAnnotationType(ReferenceBinding type) {
260
	int id = 0;
261
	if (CharOperation.equals(this.nullableName, type.sourceName))
262
		id = TypeIds.T_ConfiguredAnnotationNullable;
263
	else if (CharOperation.equals(this.nonNullName, type.sourceName))
264
		id = TypeIds.T_ConfiguredAnnotationNonNull;
265
	else if (CharOperation.equals(this.nonNullByDefaultName, type.sourceName))
266
		id = TypeIds.T_ConfiguredAnnotationNonNullByDefault;
267
	else 
268
		return;
269
	
270
	type.id = id;	// ensure annotations of this type are detected as standard annotations.
271
}
272
273
public TypeBinding getNullnessDefaultAnnotation(Scope scope) {
274
	if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
275
		return this.nullnessDefaultAnnotation = this.environment.getNullAnnotationResolved(this.nullnessDefaultAnnotation, scope);
276
	return this.nullnessDefaultAnnotation;
277
}
278
233
public char[] readableName() /*java.lang*/ {
279
public char[] readableName() /*java.lang*/ {
234
	return CharOperation.concatWith(this.compoundName, '.');
280
	return CharOperation.concatWith(this.compoundName, '.');
235
}
281
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-1 / +11 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 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 {@link 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 4289-4292 Link Here
4289
		}
4290
		}
4290
		return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType);
4291
		return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType);
4291
	}
4292
	}
4293
4294
	public void validateNullAnnotation(long tagBits, TypeReference typeRef, Annotation[] annotations) {
4295
		long nullAnnotationTagBit = tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable);
4296
		if (nullAnnotationTagBit != 0) {
4297
			TypeBinding type = typeRef.resolvedType;
4298
			if (type != null && type.isBaseType()) {
4299
				char[][] annotationName = (nullAnnotationTagBit == TagBits.AnnotationNonNull) 
4300
						? environment().getNonNullAnnotationName()
4301
						: environment().getNullableAnnotationName();
4302
				problemReporter().illegalAnnotationForBaseType(typeRef, annotations, 
4303
						annotationName[annotationName.length-1], nullAnnotationTagBit);
4304
			}
4305
		}
4306
	}
4292
}
4307
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (+97 lines)
Lines 10-15 Link Here
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 (-4 / +218 lines)
Lines 9-17 Link Here
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 - 
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 542-547 Link Here
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 :
581
		case IProblem.NullAnnotationNameMustBeQualified :
553
			return CategorizedProblem.CAT_BUILDPATH;
582
			return CategorizedProblem.CAT_BUILDPATH;
554
583
555
		default :
584
		default :
Lines 8022-8025 Link Here
8022
		trackVar.sourceStart,
8051
		trackVar.sourceStart,
8023
		trackVar.sourceEnd);	
8052
		trackVar.sourceEnd);	
8024
}
8053
}
8025
}
8054
8055
public void nullityMismatch(Expression expression, TypeBinding requiredType, int nullStatus, char[][] annotationName) {
8056
	int problemId = IProblem.RequiredNonNullButProvidedUnknown;
8057
	if ((nullStatus & FlowInfo.NULL) != 0)
8058
		problemId = IProblem.RequiredNonNullButProvidedNull;
8059
	if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
8060
		problemId = IProblem.RequiredNonNullButProvidedPotentialNull;
8061
	String[] arguments = new String[] { 
8062
			String.valueOf(CharOperation.concatWith(annotationName, '.')),
8063
			String.valueOf(requiredType.readableName())
8064
	};
8065
	String[] argumentsShort = new String[] { 
8066
			String.valueOf(annotationName[annotationName.length-1]),
8067
			String.valueOf(requiredType.shortReadableName())
8068
	};
8069
	this.handle(
8070
		problemId,
8071
		arguments,
8072
		argumentsShort,
8073
		expression.sourceStart,
8074
		expression.sourceEnd);
8075
}
8076
public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
8077
	int sourceStart = argument.type.sourceStart;
8078
	if (argument.annotations != null) {
8079
		for (int i=0; i<argument.annotations.length; i++) {
8080
			Annotation annotation = argument.annotations[i];
8081
			if (   annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable
8082
				|| annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull) 
8083
			{
8084
				sourceStart = annotation.sourceStart;
8085
				break;
8086
			}
8087
		}
8088
	}
8089
	if (inheritedAnnotationName == null) {
8090
		this.handle(
8091
			IProblem.IllegalDefinitionToNonNullParameter, 
8092
			new String[] { new String(argument.name), new String(declaringClass.readableName()) },
8093
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()) },
8094
			sourceStart,
8095
			argument.type.sourceEnd);
8096
		
8097
	} else {
8098
		this.handle(
8099
			IProblem.IllegalRedefinitionToNonNullParameter, 
8100
			new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8101
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8102
			sourceStart,
8103
			argument.type.sourceEnd);
8104
	}
8105
}
8106
public void parameterLackingNonNullAnnotation(Argument argument, ReferenceBinding declaringClass, boolean needNonNull, char[][] inheritedAnnotationName) {
8107
	this.handle(
8108
		needNonNull ? IProblem.ParameterLackingNonNullAnnotation : IProblem.ParameterLackingNullableAnnotation, 
8109
		new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8110
		new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8111
		argument.type.sourceStart,
8112
		argument.type.sourceEnd);
8113
}
8114
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl,
8115
									  MethodBinding inheritedMethod, char[][] nonNullAnnotationName) 
8116
{
8117
	MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl;
8118
	StringBuffer methodSignature = new StringBuffer();
8119
	methodSignature
8120
		.append(inheritedMethod.declaringClass.readableName())
8121
		.append('.')
8122
		.append(inheritedMethod.readableName());
8123
8124
	StringBuffer shortSignature = new StringBuffer();
8125
	shortSignature
8126
		.append(inheritedMethod.declaringClass.shortReadableName())
8127
		.append('.')
8128
		.append(inheritedMethod.shortReadableName());
8129
	int sourceStart = methodDecl.returnType.sourceStart;
8130
	Annotation[] annotations = methodDecl.annotations;
8131
	if (annotations != null) {
8132
		for (int i=0; i<annotations.length; i++) {
8133
			if (annotations[i].resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable) {
8134
				sourceStart = annotations[i].sourceStart;
8135
				break;
8136
			}
8137
		}
8138
	}
8139
	this.handle(
8140
		IProblem.IllegalReturnNullityRedefinition, 
8141
		new String[] { methodSignature.toString(), CharOperation.toString(nonNullAnnotationName)},
8142
		new String[] { shortSignature.toString(), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])},
8143
		sourceStart, 
8144
		methodDecl.returnType.sourceEnd);
8145
}
8146
public void messageSendPotentialNullReference(MethodBinding method, ASTNode location) {
8147
	String[] arguments = new String[] {new String(method.readableName())};
8148
	this.handle(
8149
		IProblem.PotentialNullMessageSendReference,
8150
		arguments,
8151
		arguments,
8152
		location.sourceStart,
8153
		location.sourceEnd);
8154
}
8155
public void messageSendRedundantCheckOnNonNull(MethodBinding method, ASTNode location) {
8156
	String[] arguments = new String[] {new String(method.readableName())  };
8157
	this.handle(
8158
		IProblem.RedundantNullCheckOnNonNullMessageSend,
8159
		arguments,
8160
		arguments,
8161
		location.sourceStart,
8162
		location.sourceEnd);
8163
}
8164
8165
public void missingNullAnnotationType(char[][] nullAnnotationName) {
8166
	String[] args = { new String(CharOperation.concatWith(nullAnnotationName, '.')) };
8167
	this.handle(IProblem.MissingNullAnnotationType, args, args, 0, 0);	
8168
}
8169
8170
public void cannotImplementIncompatibleNullness(MethodBinding currentMethod, MethodBinding inheritedMethod) {
8171
	int sourceStart = 0, sourceEnd = 0;
8172
	if (this.referenceContext instanceof TypeDeclaration) {
8173
		sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart;
8174
		sourceEnd =   ((TypeDeclaration) this.referenceContext).sourceEnd;
8175
	}
8176
	String[] problemArguments = {
8177
			new String(currentMethod.readableName()),
8178
			new String(currentMethod.declaringClass.readableName()),
8179
			new String(inheritedMethod.declaringClass.readableName())
8180
		};
8181
	String[] messageArguments = {
8182
			new String(currentMethod.shortReadableName()),
8183
			new String(currentMethod.declaringClass.shortReadableName()),
8184
			new String(inheritedMethod.declaringClass.shortReadableName())
8185
		};
8186
	this.handle(
8187
			IProblem.CannotImplementIncompatibleNullness,
8188
			problemArguments,
8189
			messageArguments,
8190
			sourceStart,
8191
			sourceEnd);
8192
}
8193
8194
public void nullAnnotationNameMustBeQualified(char[][] typeName, CompilationUnitDeclaration unitBeingCompleted) {
8195
	this.referenceContext = unitBeingCompleted;
8196
	String[] name = {new String(typeName[0])};
8197
	this.handle(IProblem.NullAnnotationNameMustBeQualified, name, name, 0, 0);
8198
}
8199
8200
public void nullAnnotationIsRedundant(AbstractMethodDeclaration sourceMethod, int i) {
8201
	int sourceStart, sourceEnd;
8202
	if (i == -1) {
8203
		MethodDeclaration methodDecl = (MethodDeclaration) sourceMethod;
8204
		sourceStart = findAnnotationSourceStart(methodDecl.annotations, methodDecl.returnType.sourceStart, TypeIds.T_ConfiguredAnnotationNonNull);
8205
		sourceEnd = methodDecl.returnType.sourceEnd;
8206
	} else {
8207
		Argument arg = sourceMethod.arguments[i];
8208
		sourceStart = arg.declarationSourceStart;
8209
		sourceEnd = arg.sourceEnd;
8210
	}
8211
	this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
8212
}
8213
8214
public void illegalAnnotationForBaseType(TypeReference type, Annotation[] annotations, char[] annotationName, long nullAnnotationTagBit) 
8215
{
8216
	int typeId = (nullAnnotationTagBit == TagBits.AnnotationNullable) 
8217
			? TypeIds.T_ConfiguredAnnotationNullable : TypeIds.T_ConfiguredAnnotationNonNull;
8218
	String[] args = new String[] { new String(annotationName), new String(type.getLastToken()) };
8219
	this.handle(IProblem.IllegalAnnotationForBaseType, 
8220
			args, 
8221
			args, 
8222
			findAnnotationSourceStart(annotations, type.sourceStart, typeId), 
8223
			type.sourceEnd);
8224
}
8225
8226
private int findAnnotationSourceStart(Annotation[] annotations, int startFallback, int typeId) {
8227
	int sourceStart = startFallback;
8228
	if (annotations != null) {
8229
		// should have a @NonNull/@Nullable annotation, search for it:
8230
		for (int j=0; j<annotations.length; j++) {
8231
			if (annotations[j].resolvedType.id == typeId) {
8232
				sourceStart = annotations[j].sourceStart;
8233
				break;
8234
			}
8235
		}
8236
	}
8237
	return sourceStart;
8238
}
8239
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+18 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 654-659 Link Here
654
889 = Resource ''{0}'' should be managed by try-with-resource
655
889 = Resource ''{0}'' should be managed by try-with-resource
655
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
656
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
656
657
658
### NULL ANNOTATIONS
659
910 = Type mismatch: required ''@{0} {1}'' but the provided value is null
660
911 = Type mismatch: required ''@{0} {1}'' but the provided value can be null
661
912 = Potential type mismatch: required ''@{0} {1}'' but nullness of the provided value is unknown
662
913 = Buildpath problem: the type {0}, which is configured as a null annotation type, cannot be resolved
663
914 = Cannot use the unqualified name ''{0}'' as an annotation name for null specification
664
915 = The return type is incompatible with the @{1} return from {0}
665
916 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
666
917 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
667
918 = Missing non-null annotation: inherited method from {1} declares this parameter as @{2}
668
919 = Missing nullable annotation: inherited method from {1} declares this parameter as @{2}
669
920 = Potential null pointer access: The method {0} may return null
670
921 = Redundant null check: The method {0} cannot return null
671
922 = The method {0} from {1} cannot implement the corresponding method from {2} due to incompatible nullness constraints
672
923 = The nullness annotation is redundant with a default that applies to this location
673
924 = The nullness annotation @{0} is not applicable for the primitive type {1}
674
657
### ELABORATIONS
675
### ELABORATIONS
658
## Access restrictions
676
## Access restrictions
659
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 / +4 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
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.core;
12
package org.eclipse.jdt.internal.core;
12
13
Lines 132-137 Link Here
132
				if (categorizedProblems == null) continue;
133
				if (categorizedProblems == null) continue;
133
				for (int i = 0, length = categorizedProblems.length; i < length; i++) {
134
				for (int i = 0, length = categorizedProblems.length; i < length; i++) {
134
					CategorizedProblem problem = categorizedProblems[i];
135
					CategorizedProblem problem = categorizedProblems[i];
136
					if (problem.getCategoryID() == CategorizedProblem.CAT_BUILDPATH)
137
						continue;	// don't report these problems against any CU, are already reported against the project
135
					if (JavaModelManager.VERBOSE){
138
					if (JavaModelManager.VERBOSE){
136
						System.out.println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
139
						System.out.println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
137
					}
140
					}
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java (-1 / +5 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.core.builder;
12
package org.eclipse.jdt.internal.core.builder;
12
13
Lines 700-705 Link Here
700
			);
701
			);
701
			// even if we're not keeping more markers, still fall through rest of the problem reporting, so that offending
702
			// even if we're not keeping more markers, still fall through rest of the problem reporting, so that offending
702
			// IsClassPathCorrect problem gets recorded since it may help locate the offending reference
703
			// IsClassPathCorrect problem gets recorded since it may help locate the offending reference
704
		} else if (problem.getCategoryID() == CategorizedProblem.CAT_BUILDPATH) {
705
			// also report other build-path problems against the project, but using a normal problem marker
706
			resource = this.javaBuilder.currentProject;
703
		}
707
		}
704
708
705
		String markerType = problem.getMarkerType();
709
		String markerType = problem.getMarkerType();

Return to bug 186342