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 lines)
Lines 1799-1804 Link Here
1799
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1799
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1800
			"	</command_line>\n" + 
1800
			"	</command_line>\n" + 
1801
			"	<options>\n" + 
1801
			"	<options>\n" + 
1802
			"		<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" + 
1803
			"		<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" + 
1804
			"		<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" + 
1805
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java (+14 lines)
Lines 380-385 Link Here
380
		expectedProblemAttributes.put("CannotDefineStaticInitializerInLocalType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
380
		expectedProblemAttributes.put("CannotDefineStaticInitializerInLocalType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
381
		expectedProblemAttributes.put("CannotExtendEnum", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
381
		expectedProblemAttributes.put("CannotExtendEnum", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
382
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
382
		expectedProblemAttributes.put("CannotHideAnInstanceMethodWithAStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
383
		expectedProblemAttributes.put("CannotImplementIncompatibleNullness", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
383
		expectedProblemAttributes.put("CannotImportPackage", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
384
		expectedProblemAttributes.put("CannotImportPackage", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
384
		expectedProblemAttributes.put("CannotInferElidedTypes", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
385
		expectedProblemAttributes.put("CannotInferElidedTypes", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
385
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
386
		expectedProblemAttributes.put("CannotInvokeSuperConstructorInEnum", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 472-477 Link Here
472
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
473
		expectedProblemAttributes.put("IllegalAccessFromTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
473
		expectedProblemAttributes.put("IllegalCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
474
		expectedProblemAttributes.put("IllegalCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
474
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
475
		expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
476
		expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
475
		expectedProblemAttributes.put("IllegalDimension", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
477
		expectedProblemAttributes.put("IllegalDimension", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
476
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
478
		expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
477
		expectedProblemAttributes.put("IllegalExtendedDimensions", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
479
		expectedProblemAttributes.put("IllegalExtendedDimensions", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
Lines 506-511 Link Here
506
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
508
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
507
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
509
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
508
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
510
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
511
		expectedProblemAttributes.put("IllegalReturnNullityRedefinition", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
512
		expectedProblemAttributes.put("IllegalRedefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
509
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
513
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
510
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
514
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
511
		expectedProblemAttributes.put("IllegalUnderscorePosition", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
515
		expectedProblemAttributes.put("IllegalUnderscorePosition", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
Lines 690-695 Link Here
690
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
694
		expectedProblemAttributes.put("MissingEnclosingInstanceForConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
691
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
695
		expectedProblemAttributes.put("MissingEnumConstantCase", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
692
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
696
		expectedProblemAttributes.put("MissingOverrideAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
697
		expectedProblemAttributes.put("MissingNullAnnotationType", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
693
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
698
		expectedProblemAttributes.put("MissingOverrideAnnotationForInterfaceMethodImplementation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
694
		expectedProblemAttributes.put("MissingReturnType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
699
		expectedProblemAttributes.put("MissingReturnType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
695
		expectedProblemAttributes.put("MissingSemiColon", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
700
		expectedProblemAttributes.put("MissingSemiColon", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
Lines 729-734 Link Here
729
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
734
		expectedProblemAttributes.put("NotVisibleField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
730
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
735
		expectedProblemAttributes.put("NotVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
731
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
736
		expectedProblemAttributes.put("NotVisibleType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
737
		expectedProblemAttributes.put("NullAnnotationNameMustBeQualified", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
732
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
738
		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
733
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
739
		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
734
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
740
		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
Lines 745-750 Link Here
745
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
751
		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
746
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
752
		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
747
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
753
		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
754
		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
755
		expectedProblemAttributes.put("ParameterLackingNullableAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
748
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
756
		expectedProblemAttributes.put("ParameterMismatch", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
749
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
757
		expectedProblemAttributes.put("ParameterizedConstructorArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
750
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
758
		expectedProblemAttributes.put("ParameterizedMethodArgumentTypeMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
Lines 771-776 Link Here
771
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
779
		expectedProblemAttributes.put("PotentiallyUnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
772
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
780
		expectedProblemAttributes.put("PotentiallyUnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
773
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
781
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
782
		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
774
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
783
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
775
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
784
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
776
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
785
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
Lines 779-788 Link Here
779
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
788
		expectedProblemAttributes.put("RedefinedLocal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
780
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
789
		expectedProblemAttributes.put("RedundantSpecificationOfTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
781
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
790
		expectedProblemAttributes.put("RedundantLocalVariableNullAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
791
		expectedProblemAttributes.put("RedundantNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
782
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
792
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
793
		expectedProblemAttributes.put("RedundantNullCheckOnNonNullMessageSend", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
783
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
794
		expectedProblemAttributes.put("RedundantNullCheckOnNullLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
784
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
795
		expectedProblemAttributes.put("RedundantSuperinterface", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
785
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
796
		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
797
		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
798
		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
799
		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
786
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
800
		expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
787
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
801
		expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
788
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
802
		expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java (+2143 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.internal.compiler.impl.CompilerOptions;
22
23
public class NullAnnotationTest extends AbstractComparableTest {
24
25
// class libraries including our default null annotation types:
26
String[] LIBS;
27
28
// names and content of custom annotations used in a few tests:
29
private static final String CUSTOM_NONNULL_NAME = "org/foo/NonNull.java";
30
private static final String CUSTOM_NONNULL_CONTENT = 
31
	"package org.foo;\n" +
32
	"import static java.lang.annotation.ElementType.*;\n" + 
33
	"import java.lang.annotation.*;\n" + 
34
	"@Retention(RetentionPolicy.CLASS)\n" + 
35
	"@Target({METHOD,PARAMETER,LOCAL_VARIABLE})\n" + 
36
	"public @interface NonNull {\n" + 
37
	"}\n";
38
private static final String CUSTOM_NULLABLE_NAME = "org/foo/Nullable.java";
39
private static final String CUSTOM_NULLABLE_CONTENT = "package org.foo;\n" +
40
	"import static java.lang.annotation.ElementType.*;\n" + 
41
	"import java.lang.annotation.*;\n" +
42
	"@Retention(RetentionPolicy.CLASS)\n" + 
43
	"@Target({METHOD,PARAMETER,LOCAL_VARIABLE})\n" + 
44
	"public @interface Nullable {\n" + 
45
	"}\n";
46
47
public NullAnnotationTest(String name) {
48
	super(name);
49
}
50
51
// Static initializer to specify tests subset using TESTS_* static variables
52
// All specified tests which do not belong to the class are skipped...
53
static {
54
//		TESTS_NAMES = new String[] { "test_nonnull_var_in_constrol_structure_3" };
55
//		TESTS_NUMBERS = new int[] { 561 };
56
//		TESTS_RANGE = new int[] { 1, 2049 };
57
}
58
59
public static Test suite() {
60
	return buildComparableTestSuite(testClass());
61
}
62
63
public static Class testClass() {
64
	return NullAnnotationTest.class;
65
}
66
67
protected void setUp() throws Exception {
68
	super.setUp();
69
	if (this.LIBS == null) {
70
		String[] defaultLibs = getDefaultClassPaths();
71
		int len = defaultLibs.length;
72
		this.LIBS = new String[len+1];
73
		System.arraycopy(defaultLibs, 0, this.LIBS, 0, len);
74
		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation.null"));
75
		if (bundleFile.isDirectory())
76
			this.LIBS[len] = bundleFile.getPath()+"/bin";
77
		else
78
			this.LIBS[len] = bundleFile.getPath();
79
	}
80
}
81
// Conditionally augment problem detection settings
82
static boolean setNullRelatedOptions = true;
83
protected Map getCompilerOptions() {
84
    Map defaultOptions = super.getCompilerOptions();
85
    if (setNullRelatedOptions) {
86
    	defaultOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
87
	    defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullReference, CompilerOptions.ERROR);
88
	    defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
89
		defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
90
		defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED);
91
		
92
		defaultOptions.put(CompilerOptions.OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation, CompilerOptions.DISABLED);
93
94
		// enable null annotations:
95
		defaultOptions.put(CompilerOptions.OPTION_AnnotationBasedNullAnalysis, CompilerOptions.ENABLED);
96
		// leave other new options at these defaults:
97
//		defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, CompilerOptions.ERROR);
98
//		defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.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(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.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(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.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(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.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(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.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 null 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(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.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 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(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
744
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
745
	runConformTestWithLibs(
746
		new String[] {
747
	"p1/X.java",
748
			"package p1;\n" +
749
			"import org.eclipse.jdt.annotation.*;\n" +
750
			"@NonNullByDefault\n" +
751
			"public class X {\n" +
752
			"    protected String getString(String s) {\n" +
753
			"        if (Character.isLowerCase(s.charAt(0)))\n" +
754
			"	        return getString(s);\n" +
755
			"	     return s;\n" +
756
			"    }\n" +
757
			"}\n",
758
	"p1/Y.java",
759
			"package p1;\n" +
760
			"import org.eclipse.jdt.annotation.*;\n" +
761
			"@NonNullByDefault\n" +
762
			"public class Y extends X {\n" +
763
			"    @Override\n" +
764
			"    protected String getString(String s) {\n" +
765
			"	     return super.getString(s);\n" +
766
			"    }\n" +
767
			"}\n",
768
		},
769
		customOptions,
770
		"");
771
}
772
// class default is nonnull, method and its super both use the default, super-call passes null
773
public void test_parameter_specification_inheritance_011() {
774
	Map customOptions = getCompilerOptions();
775
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
776
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
777
	runNegativeTestWithLibs(
778
		new String[] {
779
	"p1/X.java",
780
			"package p1;\n" +
781
			"import org.eclipse.jdt.annotation.*;\n" +
782
			"@NonNullByDefault\n" +
783
			"public class X {\n" +
784
			"    protected String getString(String s) {\n" +
785
			"        if (Character.isLowerCase(s.charAt(0)))\n" +
786
			"	        return getString(s);\n" +
787
			"	     return s;\n" +
788
			"    }\n" +
789
			"}\n",
790
	"p1/Y.java",
791
			"package p1;\n" +
792
			"import org.eclipse.jdt.annotation.*;\n" +
793
			"@NonNullByDefault\n" +
794
			"public class Y extends X {\n" +
795
			"    @Override\n" +
796
			"    protected String getString(String s) {\n" +
797
			"	     return super.getString(null);\n" +
798
			"    }\n" +
799
			"}\n",
800
		},
801
		customOptions,
802
		"----------\n" + 
803
		"1. ERROR in p1\\Y.java (at line 7)\n" + 
804
		"	return super.getString(null);\n" + 
805
		"	                       ^^^^\n" + 
806
		"Type mismatch: required \'@NonNull String\' but the provided value is null\n" + 
807
		"----------\n");
808
}
809
// methods from two super types have different null contracts.
810
// sub-class merges both using the weakest common contract 
811
public void test_parameter_specification_inheritance_012() {
812
	Map customOptions = getCompilerOptions();
813
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
814
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
815
	runConformTestWithLibs(
816
		new String[] {
817
	"p1/X.java",
818
			"package p1;\n" +
819
			"import org.eclipse.jdt.annotation.*;\n" +
820
			"public class X {\n" +
821
			"    public @Nullable String getString(String s1, @Nullable String s2, @NonNull String s3) {\n" +
822
			"	     return s1;\n" +
823
			"    }\n" +
824
			"}\n",
825
	"p1/IY.java",
826
			"package p1;\n" +
827
			"import org.eclipse.jdt.annotation.*;\n" +
828
			"public interface IY {\n" +
829
			"    @NonNull String getString(@NonNull String s1, @NonNull String s2, @Nullable String s3);\n" +
830
			"}\n",
831
	"p1/Y.java",
832
			"package p1;\n" +
833
			"import org.eclipse.jdt.annotation.*;\n" +
834
			"public class Y extends X implements IY {\n" +
835
			"    @Override\n" +
836
			"    public @NonNull String getString(@Nullable String s1, @Nullable String s2, @Nullable String s3) {\n" +
837
			"	     return \"\";\n" +
838
			"    }\n" +
839
			"}\n",
840
		},
841
		customOptions,
842
		"");
843
}
844
// methods from two super types have different null contracts.
845
// sub-class overrides this method in non-conforming ways 
846
public void test_parameter_specification_inheritance_013() {
847
	Map customOptions = getCompilerOptions();
848
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
849
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
850
	runNegativeTestWithLibs(
851
		new String[] {
852
	"p1/X.java",
853
			"package p1;\n" +
854
			"import org.eclipse.jdt.annotation.*;\n" +
855
			"public class X {\n" +
856
			"    public @Nullable String getString(String s1, @Nullable String s2, @NonNull String s3) {\n" +
857
			"	     return s1;\n" +
858
			"    }\n" +
859
			"}\n",
860
	"p1/IY.java",
861
			"package p1;\n" +
862
			"import org.eclipse.jdt.annotation.*;\n" +
863
			"public interface IY {\n" +
864
			"    @NonNull String getString(@NonNull String s1, @NonNull String s2, @Nullable String s3);\n" +
865
			"}\n",
866
	"p1/Y.java",
867
			"package p1;\n" +
868
			"import org.eclipse.jdt.annotation.*;\n" +
869
			"public class Y extends X implements IY {\n" +
870
			"    @Override\n" +
871
			"    public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" +
872
			"	     return \"\";\n" +
873
			"    }\n" +
874
			"}\n",
875
		},
876
		customOptions,
877
		"----------\n" + 
878
		"1. ERROR in p1\\Y.java (at line 5)\n" + 
879
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" + 
880
		"	       ^^^^^^^^^^^^^^^^\n" + 
881
		"The return type is incompatible with the @NonNull return from IY.getString(String, String, String)\n" + 
882
		"----------\n" + 
883
		"2. ERROR in p1\\Y.java (at line 5)\n" + 
884
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" + 
885
		"	                                  ^^^^^^\n" + 
886
		"Missing null annotation: inherited method from IY declares this parameter as @NonNull\n" + 
887
		"----------\n" + 
888
		"3. ERROR in p1\\Y.java (at line 5)\n" + 
889
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" + 
890
		"	                                             ^^^^^^^^^^^^^^^\n" + 
891
		"Illegal redefinition of parameter s2, inherited method from X declares this parameter as @Nullable\n" + 
892
		"----------\n" + 
893
		"4. ERROR in p1\\Y.java (at line 5)\n" + 
894
		"	public @Nullable String getString(String s1, @NonNull String s2, @NonNull String s3) {\n" + 
895
		"	                                                                 ^^^^^^^^^^^^^^^\n" + 
896
		"Illegal redefinition of parameter s3, inherited method from IY declares this parameter as @Nullable\n" + 
897
		"----------\n");
898
}
899
// methods from two super types have different null contracts.
900
// sub-class does not override, but should to bridge the incompatibility
901
public void test_parameter_specification_inheritance_014() {
902
	Map customOptions = getCompilerOptions();
903
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
904
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
905
	runNegativeTestWithLibs(
906
		new String[] {
907
	"p1/IY.java",
908
			"package p1;\n" +
909
			"import org.eclipse.jdt.annotation.*;\n" +
910
			"public interface IY {\n" +
911
			"    public @NonNull String getString1(String s);\n" +
912
			"    public @NonNull String getString2(String s);\n" +
913
			"    public String getString3(@Nullable String s);\n" +
914
			"    public @NonNull String getString4(@Nullable String s);\n" +
915
			"    public @NonNull String getString5(@Nullable String s);\n" +
916
			"    public @Nullable String getString6(@NonNull String s);\n" +
917
			"}\n",
918
	"p1/X.java",
919
			"package p1;\n" +
920
			"import org.eclipse.jdt.annotation.*;\n" +
921
			"public class X {\n" +
922
			"    public @Nullable String getString1(String s) {\n" + // incomp. return
923
			"	     return s;\n" +
924
			"    }\n" +
925
			"    public String getString2(String s) {\n" +			 // incomp. return
926
			"	     return s;\n" +
927
			"    }\n" +
928
			"    public String getString3(String s) {\n" +			 // incomp. arg
929
			"	     return \"\";\n" +
930
			"    }\n" +
931
			"    public @NonNull String getString4(@Nullable String s) {\n" +
932
			"	     return \"\";\n" +
933
			"    }\n" +
934
			"    public @NonNull String getString5(@NonNull String s) {\n" + // incomp. arg
935
			"	     return s;\n" +
936
			"    }\n" +
937
			"    public @NonNull String getString6(@Nullable String s) {\n" +
938
			"	     return \"\";\n" +
939
			"    }\n" +
940
			"}\n",
941
	"p1/Y.java",
942
			"package p1;\n" +
943
			"public class Y extends X implements IY {\n" +
944
			"}\n",
945
		},
946
		customOptions,
947
		"----------\n" + 
948
		"1. ERROR in p1\\Y.java (at line 2)\n" + 
949
		"	public class Y extends X implements IY {\n" + 
950
		"	             ^\n" + 
951
		"The method getString1(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + 
952
		"----------\n" + 
953
		"2. ERROR in p1\\Y.java (at line 2)\n" + 
954
		"	public class Y extends X implements IY {\n" + 
955
		"	             ^\n" + 
956
		"The method getString2(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + 
957
		"----------\n" + 
958
		"3. ERROR in p1\\Y.java (at line 2)\n" + 
959
		"	public class Y extends X implements IY {\n" + 
960
		"	             ^\n" + 
961
		"The method getString5(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + 
962
		"----------\n" + 
963
		"4. ERROR in p1\\Y.java (at line 2)\n" + 
964
		"	public class Y extends X implements IY {\n" + 
965
		"	             ^\n" + 
966
		"The method getString3(String) from class X cannot implement the corresponding method from type IY due to incompatible nullness constraints\n" + 
967
		"----------\n");
968
}
969
// a nullable return value is dereferenced without a check
970
public void test_nullable_return_001() {
971
	runNegativeTestWithLibs(
972
		new String[] {
973
			"X.java",
974
			"import org.eclipse.jdt.annotation.*;\n" +
975
			"public class X {\n" +
976
			"    @Nullable Object getObject() { return null; }\n" +
977
			"    void foo() {\n" +
978
			"        Object o = getObject();\n" +
979
			"        System.out.print(o.toString());\n" +
980
			"    }\n" +
981
			"}\n"
982
		},
983
		"----------\n" + 
984
		"1. ERROR in X.java (at line 6)\n" + 
985
		"	System.out.print(o.toString());\n" + 
986
		"	                 ^\n" + 
987
		"Potential null pointer access: The variable o may be null at this location\n" + 
988
		"----------\n");
989
}
990
// a nullable return value is dereferenced without a check, method is read from .class file
991
public void test_nullable_return_002() {
992
	runConformTestWithLibs(
993
		new String[] {
994
			"Lib.java",
995
			"import org.eclipse.jdt.annotation.*;\n" +
996
			"public class Lib {\n" +
997
			"    @Nullable Object getObject() { return null; }\n" +
998
			"}\n"
999
		},
1000
		null /*customOptions*/,
1001
		"");
1002
	runNegativeTestWithLibs(
1003
		false, // don't flush
1004
		new String[] {
1005
			"X.java",
1006
			"public class X {\n" +
1007
			"    void foo(Lib l) {\n" +
1008
			"        Object o = l.getObject();\n" +
1009
			"        System.out.print(o.toString());\n" +
1010
			"    }\n" +
1011
			"}\n"
1012
		},
1013
		null /*customOptions*/,
1014
		"----------\n" + 
1015
		"1. ERROR in X.java (at line 4)\n" + 
1016
		"	System.out.print(o.toString());\n" + 
1017
		"	                 ^\n" + 
1018
		"Potential null pointer access: The variable o may be null at this location\n" + 
1019
		"----------\n");
1020
}
1021
// a non-null return value is checked for null, method is read from .class file
1022
public void test_nonnull_return_001() {
1023
	runConformTestWithLibs(
1024
		new String[] {
1025
			"Lib.java",
1026
			"import org.eclipse.jdt.annotation.*;\n" +
1027
			"public class Lib {\n" +
1028
			"    @NonNull Object getObject() { return new Object(); }\n" +
1029
			"}\n"
1030
		},
1031
		null /*customOptions*/,
1032
		"");
1033
	runNegativeTestWithLibs(
1034
		false, // don't flush
1035
		new String[] {
1036
			"X.java",
1037
			"public class X {\n" +
1038
			"    void foo(Lib l) {\n" +
1039
			"        Object o = l.getObject();\n" +
1040
			"        if (o != null)\n" +
1041
			"            System.out.print(o.toString());\n" +
1042
			"    }\n" +
1043
			"}\n"
1044
		},
1045
		null /*customOptions*/,
1046
		"----------\n" + 
1047
		"1. ERROR in X.java (at line 4)\n" + 
1048
		"	if (o != null)\n" + 
1049
		"	    ^\n" + 
1050
		"Redundant null check: The variable o cannot be null at this location\n" + 
1051
		"----------\n");
1052
}
1053
// a non-null method returns null
1054
public void test_nonnull_return_003() {
1055
	runNegativeTestWithLibs(
1056
		new String[] {
1057
			"X.java",
1058
			"import org.eclipse.jdt.annotation.*;\n" +
1059
			"public class X {\n" +
1060
			"    @NonNull Object getObject(boolean b) {\n" +
1061
			"        if (b)\n" +
1062
			"            return null;\n" + // definite specification violation despite enclosing "if"
1063
			"        return new Object();\n" +
1064
			"    }\n" +
1065
			"}\n"
1066
		},
1067
		"----------\n" + 
1068
		"1. ERROR in X.java (at line 5)\n" + 
1069
		"	return null;\n" + 
1070
		"	       ^^^^\n" + 
1071
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1072
		"----------\n");
1073
}
1074
// a non-null method potentially returns null
1075
public void test_nonnull_return_004() {
1076
	runNegativeTestWithLibs(
1077
		new String[] {
1078
			"X.java",
1079
			"import org.eclipse.jdt.annotation.*;\n" +
1080
			"public class X {\n" +
1081
			"    @NonNull Object getObject(@Nullable Object o) {\n" +
1082
			"        return o;\n" + // 'o' is only potentially null
1083
			"    }\n" +
1084
			"}\n"
1085
		},
1086
		null /*customOptions*/,
1087
		"----------\n" + 
1088
		"1. ERROR in X.java (at line 4)\n" + 
1089
		"	return o;\n" + 
1090
		"	       ^\n" + 
1091
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1092
		"----------\n");
1093
}
1094
// a non-null method returns its non-null argument
1095
public void test_nonnull_return_005() {
1096
	Map customOptions = getCompilerOptions();
1097
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1098
	runConformTestWithLibs(
1099
		new String[] {
1100
			"X.java",
1101
			"import org.eclipse.jdt.annotation.*;\n" +
1102
			"public class X {\n" +
1103
			"    @NonNull Object getObject(@NonNull Object o) {\n" +
1104
			"        return o;\n" +
1105
			"    }\n" +
1106
			"}\n"
1107
		},
1108
		customOptions,
1109
		"");
1110
}
1111
//a non-null method has insufficient nullness info for its return value
1112
public void test_nonnull_return_006() {
1113
	runNegativeTestWithLibs(
1114
		new String[] {
1115
			"X.java",
1116
			"import org.eclipse.jdt.annotation.*;\n" +
1117
			"public class X {\n" +
1118
			"    @NonNull Object getObject(Object o) {\n" +
1119
			"        return o;\n" +
1120
			"    }\n" +
1121
			"}\n"
1122
		},
1123
		"----------\n" + 
1124
		"1. WARNING in X.java (at line 4)\n" + 
1125
		"	return o;\n" + 
1126
		"	       ^\n" + 
1127
		"Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown\n" + 
1128
		"----------\n");
1129
}
1130
// a result from a nullable method is directly dereferenced
1131
public void test_nonnull_return_007() {
1132
	runNegativeTestWithLibs(
1133
		new String[] {
1134
			"X.java",
1135
			"import org.eclipse.jdt.annotation.*;\n" +
1136
			"public class X {\n" +
1137
			"    @Nullable Object getObject() {\n" +
1138
			"        return null;\n" +
1139
			"    }\n" +
1140
			"    void test() {\n" +
1141
			"        getObject().toString();\n" +
1142
			"    }\n" +
1143
			"}\n"
1144
		},
1145
		"----------\n" + 
1146
		"1. ERROR in X.java (at line 7)\n" + 
1147
		"	getObject().toString();\n" + 
1148
		"	^^^^^^^^^^^\n" + 
1149
		"Potential null pointer access: The method getObject() may return null\n" + 
1150
		"----------\n");
1151
}
1152
// a result from a nonnull method is directly checked for null: redundant
1153
public void test_nonnull_return_008() {
1154
	Map customOptions = getCompilerOptions();
1155
	customOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
1156
	runNegativeTestWithLibs(
1157
		new String[] {
1158
			"X.java",
1159
			"import org.eclipse.jdt.annotation.*;\n" +
1160
			"public class X {\n" +
1161
			"    @NonNull Object getObject() {\n" +
1162
			"        return new Object();\n" +
1163
			"    }\n" +
1164
			"    void test() {\n" +
1165
			"        if (getObject() == null)\n" +
1166
			"		     throw new RuntimeException();\n" +
1167
			"    }\n" +
1168
			"}\n"
1169
		},
1170
		customOptions,
1171
		"----------\n" + 
1172
		"1. ERROR in X.java (at line 7)\n" + 
1173
		"	if (getObject() == null)\n" + 
1174
		"	    ^^^^^^^^^^^\n" + 
1175
		"Redundant null check: The method getObject() cannot return null\n" + 
1176
		"----------\n");
1177
}
1178
// a result from a nonnull method is directly checked for null (from local): redundant
1179
public void test_nonnull_return_009() {
1180
	Map customOptions = getCompilerOptions();
1181
	customOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
1182
	runNegativeTestWithLibs(
1183
		new String[] {
1184
			"X.java",
1185
			"import org.eclipse.jdt.annotation.*;\n" +
1186
			"public class X {\n" +
1187
			"    @NonNull Object getObject() {\n" +
1188
			"        return new Object();\n" +
1189
			"    }\n" +
1190
			"    void test() {\n" +
1191
			"        Object left = null;\n" +
1192
			"        if (left != getObject())\n" +
1193
			"		     throw new RuntimeException();\n" +
1194
			"    }\n" +
1195
			"}\n"
1196
		},
1197
		customOptions,
1198
		"----------\n" + 
1199
		"1. ERROR in X.java (at line 8)\n" + 
1200
		"	if (left != getObject())\n" + 
1201
		"	    ^^^^\n" + 
1202
		"Redundant null check: The variable left can only be null at this location\n" + 
1203
		"----------\n" + 
1204
		"2. ERROR in X.java (at line 8)\n" + 
1205
		"	if (left != getObject())\n" + 
1206
		"	            ^^^^^^^^^^^\n" + 
1207
		"Redundant null check: The method getObject() cannot return null\n" + 
1208
		"----------\n");
1209
}
1210
// a result from a nullable method is assigned and checked for null (from local): not redundant
1211
// see also Bug 336428 - [compiler][null] bogus warning "redundant null check" in condition of do {} while() loop
1212
public void test_nonnull_return_010() {
1213
	Map customOptions = getCompilerOptions();
1214
	customOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
1215
	runNegativeTestWithLibs(
1216
		new String[] {
1217
			"X.java",
1218
			"import org.eclipse.jdt.annotation.*;\n" +
1219
			"public class X {\n" +
1220
			"    @Nullable X getX() {\n" +
1221
			"        return new X();\n" +
1222
			"    }\n" +
1223
			"    void test() {\n" +
1224
			"        X left = this;\n" +
1225
			"        do {\n" +
1226
			"            if (left == null) \n" +
1227
			"	   	         throw new RuntimeException();\n" +
1228
			"        } while ((left = left.getX()) != null);\n" + // no warning/error here!
1229
			"    }\n" +
1230
			"}\n"
1231
		},
1232
		customOptions,
1233
		"----------\n" + 
1234
		"1. ERROR in X.java (at line 9)\n" + 
1235
		"	if (left == null) \n" + 
1236
		"	    ^^^^\n" + 
1237
		"Null comparison always yields false: The variable left cannot be null at this location\n" + 
1238
		"----------\n");
1239
}
1240
// a non-null method returns a checked-for null value, but that branch is dead code
1241
public void test_nonnull_return_011() {
1242
	Map customOptions = getCompilerOptions();
1243
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1244
	runNegativeTestWithLibs(
1245
		new String[] {
1246
			"X.java",
1247
			"import org.eclipse.jdt.annotation.*;\n" +
1248
			"@NonNullByDefault\n" +
1249
			"public class X {\n" +
1250
			"    Object getObject(Object dubious) {\n" +
1251
			"        if (dubious == null)\n" + // redundant
1252
			"            return dubious;\n" + // definitely null, but not reported inside dead code
1253
			"        return new Object();\n" +
1254
			"    }\n" +
1255
			"}\n"
1256
		},
1257
		customOptions,
1258
		"----------\n" + 
1259
		"1. ERROR in X.java (at line 5)\n" + 
1260
		"	if (dubious == null)\n" + 
1261
		"	    ^^^^^^^\n" + 
1262
		"Null comparison always yields false: The variable dubious cannot be null at this location\n" + 
1263
		"----------\n" + 
1264
		"2. WARNING in X.java (at line 6)\n" + 
1265
		"	return dubious;\n" + 
1266
		"	^^^^^^^^^^^^^^^\n" + 
1267
		"Dead code\n" + 
1268
		"----------\n");
1269
}
1270
// a non-null method returns a definite null from a conditional expression
1271
// requires the fix for Bug 354554 - [null] conditional with redundant condition yields weak error message
1272
// TODO(SH): ENABLE!
1273
public void _test_nonnull_return_012() {
1274
	Map customOptions = getCompilerOptions();
1275
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1276
	runNegativeTestWithLibs(
1277
		new String[] {
1278
			"X.java",
1279
			"import org.eclipse.jdt.annotation.*;\n" +
1280
			"@NonNullByDefault\n" +
1281
			"public class X {\n" +
1282
			"    Object getObject(Object dubious) {\n" +
1283
			"        return dubious == null ? dubious : null;\n" +
1284
			"    }\n" +
1285
			"}\n"
1286
		},
1287
		customOptions,
1288
		"----------\n" + 
1289
		"1. ERROR in X.java (at line 5)\n" + 
1290
		"	return dubious == null ? dubious : null;\n" + 
1291
		"	       ^^^^^^^\n" + 
1292
		"Null comparison always yields false: The variable dubious cannot be null at this location\n" + 
1293
		"----------\n" + 
1294
		"2. ERROR in X.java (at line 5)\n" + 
1295
		"	return dubious == null ? dubious : null;\n" + 
1296
		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
1297
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1298
		"----------\n");
1299
}
1300
// don't apply any default annotations to return void
1301
public void test_nonnull_return_013() {
1302
	Map customOptions = getCompilerOptions();
1303
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1304
	runConformTestWithLibs(
1305
		new String[] {
1306
			"X.java",
1307
			"import org.eclipse.jdt.annotation.*;\n" +
1308
			"@NonNullByDefault\n" +
1309
			"public class X {\n" +
1310
			"    void getObject() {}\n" +
1311
			"}\n",
1312
			"Y.java",
1313
			"public class Y extends X {\n" +
1314
			"    @Override\n" +
1315
			"    void getObject() {}\n" + // don't complain, void takes no (default) annotation
1316
			"}\n"
1317
		},
1318
		customOptions,
1319
		"");
1320
}
1321
//suppress an error regarding null-spec violation
1322
public void test_suppress_001() {
1323
	Map customOptions = getCompilerOptions();
1324
	customOptions.put(CompilerOptions.OPTION_SuppressOptionalErrors, CompilerOptions.ENABLED);
1325
	runConformTestWithLibs(
1326
			new String[] {
1327
				"X.java",
1328
				"import org.eclipse.jdt.annotation.*;\n" +
1329
				"public class X {\n" +
1330
				"    @SuppressWarnings(\"null\")\n" +
1331
				"    @NonNull Object getObject(@Nullable Object o) {\n" +
1332
				"        return o;\n" + // 'o' is only potentially null
1333
				"    }\n" +
1334
				"}\n"
1335
			},
1336
			customOptions,
1337
			"");	
1338
}
1339
// mixed use of fully qualified name / explicit import
1340
public void test_annotation_import_001() {
1341
	Map customOptions = getCompilerOptions();
1342
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1343
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable");
1344
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
1345
	runConformTestWithLibs(
1346
		new String[] {
1347
			CUSTOM_NULLABLE_NAME,
1348
			CUSTOM_NULLABLE_CONTENT,
1349
			CUSTOM_NONNULL_NAME,
1350
			CUSTOM_NONNULL_CONTENT,
1351
			"Lib.java",
1352
			"public class Lib {\n" +
1353
			"    @org.foo.NonNull Object getObject() { return new Object(); }\n" + 	// FQN
1354
			"}\n",
1355
			"X.java",
1356
			"import org.foo.NonNull;\n" +											// explicit import
1357
			"public class X {\n" +
1358
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
1359
			"        return l.getObject();\n" +
1360
			"    }\n" +
1361
			"}\n"
1362
		},
1363
		customOptions,
1364
		"");
1365
}
1366
1367
// use of explicit imports throughout
1368
public void test_annotation_import_002() {
1369
	Map customOptions = getCompilerOptions();
1370
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1371
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable");
1372
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
1373
	runConformTest(
1374
		new String[] {
1375
			CUSTOM_NULLABLE_NAME,
1376
			CUSTOM_NULLABLE_CONTENT,
1377
			CUSTOM_NONNULL_NAME,
1378
			CUSTOM_NONNULL_CONTENT,
1379
			"Lib.java",
1380
			"import org.foo.NonNull;\n" +
1381
			"public class Lib {\n" +
1382
			"    @NonNull Object getObject() { return new Object(); }\n" +
1383
			"}\n",
1384
			"X.java",
1385
			"import org.foo.NonNull;\n" +
1386
			"public class X {\n" +
1387
			"    @NonNull Object getObject(@org.foo.Nullable String dummy, @NonNull Lib l) {\n" +
1388
			"        Object o = l.getObject();" +
1389
			"        return o;\n" +
1390
			"    }\n" +
1391
			"}\n"
1392
		},
1393
		customOptions,
1394
		"");
1395
}
1396
// explicit import of existing annotation types
1397
// using a Lib without null specifications
1398
public void test_annotation_import_005() {
1399
	Map customOptions = getCompilerOptions();
1400
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1401
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1402
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull");
1403
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull");
1404
	runNegativeTest(
1405
		true/*shouldFlushOutputDirectory*/,
1406
		new String[] {
1407
			"org/foo/MayBeNull.java",
1408
			"package org.foo;\n" +
1409
			"import java.lang.annotation.*;\n" +
1410
			"@Retention(RetentionPolicy.CLASS)\n" +
1411
			"public @interface MayBeNull {}\n",
1412
			
1413
			"org/foo/MustNotBeNull.java",
1414
			"package org.foo;\n" +
1415
			"import java.lang.annotation.*;\n" +
1416
			"@Retention(RetentionPolicy.CLASS)\n" +
1417
			"public @interface MustNotBeNull {}\n",
1418
1419
			"Lib.java",
1420
			"public class Lib {\n" +
1421
			"    Object getObject() { return new Object(); }\n" +
1422
			"}\n",
1423
			"X.java",
1424
			"import org.foo.*;\n" +
1425
			"public class X {\n" +
1426
			"    @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1427
			"        return l.getObject();\n" +
1428
			"    }\n" +
1429
			"}\n",
1430
			
1431
		},
1432
		null /*no libs*/,
1433
		customOptions,
1434
		"----------\n" + 
1435
		"1. ERROR in X.java (at line 4)\n" + 
1436
		"	return l.getObject();\n" + 
1437
		"	       ^^^^^^^^^^^^^\n" + 
1438
		"Potential type mismatch: required \'@MustNotBeNull Object\' but nullness of the provided value is unknown\n" + 
1439
		"----------\n",
1440
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1441
}
1442
// a non-null method returns a value obtained from an unannotated method, missing annotation types
1443
public void test_annotation_import_006() {
1444
	Map customOptions = getCompilerOptions();
1445
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1446
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1447
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull");
1448
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull");
1449
	runNegativeTest(
1450
		true/*shouldFlushOutputDirectory*/,
1451
		new String[] {
1452
			"Lib.java",
1453
			"public class Lib {\n" +
1454
			"    Object getObject() { return new Object(); }\n" +
1455
			"}\n",
1456
			"X.java",
1457
			"public class X {\n" +
1458
			"    @MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" +
1459
			"        return l.getObject();\n" +
1460
			"    }\n" +
1461
			"}\n"
1462
		},
1463
		null /* no libs */,
1464
		customOptions,
1465
		"----------\n" +
1466
		"1. ERROR in X.java (at line 2)\n" + 
1467
		"	@MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" + 
1468
		"	 ^^^^^^^^^^^^^\n" + 
1469
		"MustNotBeNull cannot be resolved to a type\n" + 
1470
		"----------\n" + 
1471
		"2. ERROR in X.java (at line 2)\n" + 
1472
		"	@MustNotBeNull Object getObject(@MustNotBeNull Lib l) {\n" + 
1473
		"	                                 ^^^^^^^^^^^^^\n" + 
1474
		"MustNotBeNull cannot be resolved to a type\n" + 
1475
		"----------\n",
1476
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1477
}
1478
// using nullness defaulting to nonnull, missing annotation types
1479
public void test_annotation_import_007() {
1480
	Map customOptions = getCompilerOptions();
1481
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1482
	customOptions.put(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, CompilerOptions.ERROR);
1483
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.MayBeNull");
1484
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.MustNotBeNull");
1485
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1486
	runNegativeTest(
1487
		true/*shouldFlushOutputDirectory*/,
1488
		new String[] {
1489
			"Lib.java",
1490
			"public class Lib {\n" +
1491
			"    Object getObject() { return new Object(); }\n" +
1492
			"}\n",
1493
			"X.java",
1494
			"public class X {\n" +
1495
			"    Object getObject(Lib l) {\n" +
1496
			"        return l.getObject();\n" +
1497
			"    }\n" +
1498
			"}\n"
1499
		},
1500
		this.LIBS,
1501
		customOptions,
1502
		"----------\n" + 
1503
		"1. ERROR in Lib.java (at line 1)\n" + 
1504
		"	public class Lib {\n" + 
1505
		"	^\n" + 
1506
		"Buildpath problem: the type org.foo.MustNotBeNull which is configured as a null annotation type cannot be resolved\n" + 
1507
		"----------\n",
1508
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
1509
}
1510
1511
// a null annotation is illegally used on a class:
1512
public void test_illegal_annotation_001() {
1513
	runNegativeTest(
1514
		new String[] {
1515
			"X.java",
1516
			"import org.eclipse.jdt.annotation.*;\n" +
1517
			"@NonNull public class X {\n" +
1518
			"}\n"
1519
		},
1520
		"----------\n" + 
1521
		"1. ERROR in X.java (at line 2)\n" + 
1522
		"	@NonNull public class X {\n" + 
1523
		"	^^^^^^^^\n" + 
1524
		"The annotation @NonNull is disallowed for this location\n" + 
1525
		"----------\n",
1526
		this.LIBS,
1527
		false/*shouldFlush*/);
1528
}
1529
// this test has been removed:
1530
// setting default to nullable, default applies to a parameter
1531
// public void test_default_nullness_001()
1532
1533
// a null annotation is illegally defined by its simple name
1534
public void test_illegal_annotation_002() {
1535
	Map customOptions = getCompilerOptions();
1536
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "NichtNull");
1537
	runNegativeTestWithLibs(
1538
		new String[] {
1539
			"X.java",
1540
			"public class X {\n" +
1541
			"}\n"
1542
		},
1543
		customOptions,
1544
		"----------\n" + 
1545
		"1. ERROR in X.java (at line 0)\n" + 
1546
		"	public class X {\n" + 
1547
		"	^\n" + 
1548
		"Cannot use the unqualified name \'NichtNull\' as an annotation name for null specification\n" + 
1549
		"----------\n");
1550
}
1551
public void test_default_nullness_002() {
1552
	Map customOptions = getCompilerOptions();
1553
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1554
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1555
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1556
	runNegativeTestWithLibs(
1557
		new String[] {
1558
			"X.java",
1559
			"import org.eclipse.jdt.annotation.*;\n" +
1560
			"public class X {\n" +
1561
			"    Object getObject(@Nullable Object o) {\n" +
1562
			"        return new Object();\n" +
1563
			"    }\n" +
1564
			"}\n",
1565
			"Y.java",
1566
			"import org.eclipse.jdt.annotation.*;\n" +
1567
			"public class Y extends X {\n" +
1568
			"    @Override\n" +
1569
			"    @Nullable Object getObject(Object o) {\n" + // complain illegal return redef and inherited annot is not repeated
1570
			"        return o;\n" +
1571
			"    }\n" +
1572
			"}\n",
1573
		},
1574
		customOptions,
1575
		// main error:
1576
		"----------\n" + 
1577
		"1. ERROR in Y.java (at line 4)\n" + 
1578
		"	@Nullable Object getObject(Object o) {\n" + 
1579
		"	^^^^^^^^^^^^^^^^\n" + 
1580
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1581
		"----------\n" +
1582
		// additional error:
1583
		"2. ERROR in Y.java (at line 4)\n" + 
1584
		"	@Nullable Object getObject(Object o) {\n" + 
1585
		"	                           ^^^^^^\n" + 
1586
		"Illegal redefinition of parameter o, inherited method from X declares this parameter as @Nullable\n" + 
1587
		"----------\n");
1588
}
1589
// package default is non-null
1590
public void test_default_nullness_003() {
1591
	Map customOptions = getCompilerOptions();
1592
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1593
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1594
	runNegativeTestWithLibs(
1595
		new String[] {
1596
	"p1/X.java",
1597
			"package p1;\n" +
1598
			"import org.eclipse.jdt.annotation.*;\n" +
1599
			"@NonNullByDefault\n" +
1600
			"public class X {\n" +
1601
			"    protected Object getObject(@Nullable Object o) {\n" +
1602
			"        return new Object();\n" +
1603
			"    }\n" +
1604
			"}\n",
1605
	"p2/package-info.java",
1606
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1607
			"package p2;\n",
1608
	"p2/Y.java",
1609
			"package p2;\n" +
1610
			"import org.eclipse.jdt.annotation.*;\n" +
1611
			"public class Y extends p1.X {\n" +
1612
			"    @Override\n" +
1613
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" +
1614
			"        bar(o);\n" +
1615
			"        return o;\n" +
1616
			"    }\n" +
1617
			"	 void bar(Object o2) { }\n" + // parameter is nonnull per package default
1618
			"}\n"
1619
		},
1620
		customOptions,
1621
		"----------\n" + 
1622
		"1. ERROR in p2\\Y.java (at line 5)\n" + 
1623
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" + 
1624
		"	          ^^^^^^^^^^^^^^^^\n" + 
1625
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1626
		"----------\n" + 
1627
		"2. ERROR in p2\\Y.java (at line 6)\n" + 
1628
		"	bar(o);\n" + 
1629
		"	    ^\n" + 
1630
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1631
		"----------\n");
1632
}
1633
// package level default is consumed from package-info.class
1634
public void test_default_nullness_003a() {
1635
	Map customOptions = getCompilerOptions();
1636
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1637
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1638
	runConformTestWithLibs(
1639
		new String[] {
1640
	"p1/X.java",
1641
			"package p1;\n" +
1642
			"import org.eclipse.jdt.annotation.*;\n" +
1643
			"@NonNullByDefault\n" +
1644
			"public class X {\n" +
1645
			"    protected Object getObject(@Nullable Object o) {\n" +
1646
			"        return new Object();\n" +
1647
			"    }\n" +
1648
			"	 protected void bar(Object o2) { }\n" + // parameter is nonnull per type default
1649
			"}\n",
1650
	"p2/package-info.java",
1651
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1652
			"package p2;\n",
1653
			},
1654
			customOptions,
1655
			"");
1656
	// check if default is visible from package-info.class.
1657
	runNegativeTestWithLibs(
1658
		false, // don't flush
1659
		new String[] {
1660
	"p2/Y.java",
1661
			"package p2;\n" +
1662
			"import org.eclipse.jdt.annotation.*;\n" +
1663
			"public class Y extends p1.X {\n" +
1664
			"    @Override\n" +
1665
			"    protected @Nullable Object getObject(@Nullable Object o) {\n" + // can't override inherited default nonnull 
1666
			"        bar(o);\n" + // parameter is nonnull in super class's .class file
1667
			"        accept(o);\n" +
1668
			"        return o;\n" +
1669
			"    }\n" +
1670
			"    void accept(Object a) {}\n" + // governed by package level default
1671
			"}\n"
1672
		},
1673
		customOptions,
1674
		"----------\n" + 
1675
		"1. ERROR in p2\\Y.java (at line 5)\n" + 
1676
		"	protected @Nullable Object getObject(@Nullable Object o) {\n" + 
1677
		"	          ^^^^^^^^^^^^^^^^\n" + 
1678
		"The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + 
1679
		"----------\n" + 
1680
		"2. ERROR in p2\\Y.java (at line 6)\n" + 
1681
		"	bar(o);\n" + 
1682
		"	    ^\n" + 
1683
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1684
		"----------\n" + 
1685
		"3. ERROR in p2\\Y.java (at line 7)\n" + 
1686
		"	accept(o);\n" + 
1687
		"	       ^\n" + 
1688
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1689
		"----------\n");
1690
}
1691
// don't apply type-level default to non-reference type
1692
public void test_default_nullness_004() {
1693
	Map customOptions = getCompilerOptions();
1694
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1695
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1696
	runConformTestWithLibs(
1697
		new String[] {
1698
	"p1/X.java",
1699
			"package p1;\n" +
1700
			"import org.eclipse.jdt.annotation.*;\n" +
1701
			"@NonNullByDefault\n" +
1702
			"public class X {\n" +
1703
			"    protected Object getObject(boolean o) {\n" +
1704
			"        return new Object();\n" +
1705
			"    }\n" +
1706
			"}\n",
1707
	"p2/Y.java",
1708
			"package p2;\n" +
1709
			"import org.eclipse.jdt.annotation.*;\n" +
1710
			"public class Y extends p1.X {\n" +
1711
			"    @Override\n" +
1712
			"    protected @NonNull Object getObject(boolean o) {\n" +
1713
			"        return o ? this : new Object();\n" +
1714
			"    }\n" +
1715
			"}\n"
1716
		},
1717
		customOptions,
1718
		"");
1719
}
1720
// package default is non-null
1721
// see also Bug 354536 - compiling package-info.java still depends on the order of compilation units
1722
public void test_default_nullness_005() {
1723
	Map customOptions = getCompilerOptions();
1724
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1725
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1726
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
1727
	runNegativeTestWithLibs(
1728
		new String[] {
1729
	"p1/X.java",
1730
			"package p1;\n" +
1731
			"public class X {\n" +
1732
			"    class Inner {" +
1733
			"        protected Object getObject(String s) {\n" +
1734
			"            return null;\n" +
1735
			"        }\n" +
1736
			"    }\n" +
1737
			"}\n",
1738
	"p1/package-info.java",
1739
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1740
			"package p1;\n",
1741
	CUSTOM_NONNULL_NAME,
1742
			CUSTOM_NONNULL_CONTENT
1743
		},
1744
		customOptions,
1745
		"----------\n" + 
1746
		"1. ERROR in p1\\X.java (at line 4)\n" + 
1747
		"	return null;\n" + 
1748
		"	       ^^^^\n" + 
1749
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1750
		"----------\n");
1751
}
1752
// package default is non-null, package-info.java read before the annotation type
1753
// compile order: beginToCompile(X.Inner) triggers reading of package-info.java before the annotation type was read
1754
public void test_default_nullness_006() {
1755
	Map customOptions = getCompilerOptions();
1756
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1757
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1758
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
1759
	runNegativeTestWithLibs(
1760
		new String[] {
1761
	"p1/package-info.java",
1762
			"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
1763
			"package p1;\n",
1764
	"p1/X.java",
1765
			"package p1;\n" +
1766
			"public class X {\n" +
1767
			"    class Inner {" +
1768
			"        protected Object getObject(String s) {\n" +
1769
			"            return null;\n" +
1770
			"        }\n" +
1771
			"    }\n" +
1772
			"}\n",
1773
	CUSTOM_NONNULL_NAME,
1774
			CUSTOM_NONNULL_CONTENT
1775
		},
1776
		customOptions,
1777
		"----------\n" + 
1778
		"1. ERROR in p1\\X.java (at line 4)\n" + 
1779
		"	return null;\n" + 
1780
		"	       ^^^^\n" + 
1781
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
1782
		"----------\n");
1783
}
1784
// global default nonnull, but return may be null 
1785
public void test_default_nullness_007() {
1786
	Map customOptions = getCompilerOptions();
1787
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1788
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1789
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1790
	runNegativeTestWithLibs(
1791
		new String[] {
1792
			"X.java",
1793
			"import org.eclipse.jdt.annotation.*;\n" +
1794
			"public class X {\n" +
1795
			"    @Nullable Object dangerous() {\n" +
1796
			"        return null;\n" + 
1797
			"    }\n" +
1798
			"    Object broken() {\n" +
1799
			"        return dangerous();\n" +
1800
			"    }\n" +
1801
			"}\n",
1802
1803
		},
1804
		customOptions,
1805
		"----------\n" + 
1806
		"1. ERROR in X.java (at line 7)\n" + 
1807
		"	return dangerous();\n" + 
1808
		"	       ^^^^^^^^^^^\n" + 
1809
		"Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + 
1810
		"----------\n");
1811
}
1812
1813
// cancel type level default to comply with super specification
1814
public void test_default_nullness_008() {
1815
	Map customOptions = getCompilerOptions();
1816
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1817
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1818
	runConformTestWithLibs(
1819
		new String[] {
1820
	"p1/X.java",
1821
			"package p1;\n" +
1822
			"public class X {\n" +
1823
			"    protected Object getObject(Object o) {\n" +
1824
			"        return new Object();\n" +
1825
			"    }\n" +
1826
			"}\n",
1827
	"p2/Y.java",
1828
			"package p2;\n" +
1829
			"import org.eclipse.jdt.annotation.*;\n" +
1830
			"@NonNullByDefault\n" +
1831
			"public class Y extends p1.X {\n" +
1832
			"    @Override\n" +
1833
			"    @NonNullByDefault(false)\n" +
1834
			"    protected Object getObject(Object o) {\n" +
1835
			"        if (o.toString().length() == 0)\n" + // dereference without a warning
1836
			"	        return null;\n" + // return null without a warning
1837
			"        return o.toString();\n" +
1838
			"    }\n" +
1839
			"}\n"
1840
		},
1841
		customOptions,
1842
		"");
1843
}
1844
1845
// cancel outer type level default to comply with super specification
1846
public void test_default_nullness_009() {
1847
	Map customOptions = getCompilerOptions();
1848
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1849
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1850
	runNegativeTestWithLibs(
1851
		new String[] {
1852
	"p1/X.java",
1853
			"package p1;\n" +
1854
			"public class X {\n" +
1855
			"    protected Object getObject(Object o) {\n" +
1856
			"        return new Object();\n" +
1857
			"    }\n" +
1858
			"}\n",
1859
	"p2/Y.java",
1860
			"package p2;\n" +
1861
			"import org.eclipse.jdt.annotation.*;\n" +
1862
			"@NonNullByDefault\n" +
1863
			"public class Y { \n" +
1864
			"    @NonNullByDefault(false)\n" +
1865
			"    static class Z extends p1.X {\n" +
1866
			"        @Override\n" +
1867
			"        protected Object getObject(Object o) {\n" +
1868
			"            if (o.toString().length() == 0) {\n" +
1869
			"                o = null;\n" + // assign null without a warning
1870
			"                bar(o); // error: arg is declared @NonNull\n" +
1871
			"	             return null;\n" +
1872
			"            }\n" +
1873
			"            return o.toString();\n" +
1874
			"        }\n" +
1875
			"        String bar(@NonNull Object o) {\n" +
1876
			"            return getObject(o).toString();" +
1877
			"        }\n" +
1878
			"    }\n" +
1879
			"}\n"
1880
		},
1881
		customOptions,
1882
		"----------\n" +
1883
		"1. ERROR in p2\\Y.java (at line 11)\n" + 
1884
		"	bar(o); // error: arg is declared @NonNull\n" +
1885
		"	    ^\n" +
1886
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" +
1887
		"----------\n");
1888
}
1889
// non-null declarations are redundant within a default scope.
1890
public void test_default_nullness_010() {
1891
	Map customOptions = getCompilerOptions();
1892
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1893
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1894
	runConformTestWithLibs(
1895
		new String[] {
1896
	"p2/Y.java",
1897
			"package p2;\n" +
1898
			"import org.eclipse.jdt.annotation.*;\n" +
1899
			"@NonNullByDefault\n" +
1900
			"public class Y {\n" +
1901
			"    protected @NonNull Object getObject(@NonNull Object o) {\n" +
1902
			"        return o;\n" +
1903
			"    }\n" +
1904
			"}\n"
1905
		},
1906
		customOptions,
1907
		"----------\n" + 
1908
		"1. WARNING in p2\\Y.java (at line 5)\n" + 
1909
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" + 
1910
		"	          ^^^^^^^^^^^^^^^\n" + 
1911
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1912
		"----------\n" + 
1913
		"2. WARNING in p2\\Y.java (at line 5)\n" + 
1914
		"	protected @NonNull Object getObject(@NonNull Object o) {\n" + 
1915
		"	                                    ^^^^^^^^^^^^^^^^^\n" + 
1916
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1917
		"----------\n");
1918
}
1919
// a nonnull variable is dereferenced in a loop
1920
public void test_nonnull_var_in_constrol_structure_1() {
1921
	Map customOptions = getCompilerOptions();
1922
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1923
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1924
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1925
	runNegativeTestWithLibs(
1926
		new String[] {
1927
			"X.java",
1928
			"import org.eclipse.jdt.annotation.*;\n" +
1929
			"public class X {\n" +
1930
			"    void print4(@NonNull String s) {\n" +
1931
			"        for (int i=0; i<4; i++)\n" +
1932
			"             print(s);\n" + 
1933
			"    }\n" +
1934
			"    void print5(@Nullable String s) {\n" +
1935
			"        for (int i=0; i<5; i++)\n" +
1936
			"             print(s);\n" + 
1937
			"    }\n" +
1938
			"    void print6(boolean b) {\n" +
1939
			"        String s = b ? null : \"\";\n" +
1940
			"        for (int i=0; i<5; i++)\n" +
1941
			"             print(s);\n" + 
1942
			"    }\n" +
1943
			"    void print(@NonNull String s) {\n" +
1944
			"        System.out.print(s);\n" +
1945
			"    }\n" +
1946
			"}\n",
1947
1948
		},
1949
		customOptions,
1950
		"----------\n" + 
1951
		"1. WARNING in X.java (at line 3)\n" + 
1952
		"	void print4(@NonNull String s) {\n" + 
1953
		"	            ^^^^^^^^^^^^^^^^^\n" + 
1954
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1955
		"----------\n" + 
1956
		"2. ERROR in X.java (at line 9)\n" + 
1957
		"	print(s);\n" + 
1958
		"	      ^\n" + 
1959
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
1960
		"----------\n" + 
1961
		"3. ERROR in X.java (at line 14)\n" + 
1962
		"	print(s);\n" + 
1963
		"	      ^\n" + 
1964
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
1965
		"----------\n" + 
1966
		"4. WARNING in X.java (at line 16)\n" + 
1967
		"	void print(@NonNull String s) {\n" + 
1968
		"	           ^^^^^^^^^^^^^^^^^\n" + 
1969
		"The nullness annotation is redundant with a default that applies to this location\n" + 
1970
		"----------\n");
1971
}
1972
// a nonnull variable is dereferenced in a finally block
1973
public void test_nonnull_var_in_constrol_structure_2() {
1974
	Map customOptions = getCompilerOptions();
1975
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
1976
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
1977
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1978
	runNegativeTestWithLibs(
1979
		new String[] {
1980
			"X.java",
1981
			"import org.eclipse.jdt.annotation.*;\n" +
1982
			"public class X {\n" +
1983
			"    void print4(String s) {\n" +
1984
			"        try { /*empty*/ } finally {\n" +
1985
			"             print(s);\n" +
1986
			"        }\n" + 
1987
			"    }\n" +
1988
			"    void print5(@Nullable String s) {\n" +
1989
			"        try { /*empty*/ } finally {\n" +
1990
			"             print(s);\n" +
1991
			"        }\n" + 
1992
			"    }\n" +
1993
			"    void print6(boolean b) {\n" +
1994
			"        String s = b ? null : \"\";\n" +
1995
			"        try { /*empty*/ } finally {\n" +
1996
			"             print(s);\n" +
1997
			"        }\n" + 
1998
			"    }\n" +
1999
			"    void print(String s) {\n" +
2000
			"        System.out.print(s);\n" +
2001
			"    }\n" +
2002
			"}\n",
2003
2004
		},
2005
		customOptions,
2006
		"----------\n" + 
2007
		"1. ERROR in X.java (at line 10)\n" + 
2008
		"	print(s);\n" + 
2009
		"	      ^\n" + 
2010
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2011
		"----------\n" + 
2012
		"2. ERROR in X.java (at line 16)\n" + 
2013
		"	print(s);\n" + 
2014
		"	      ^\n" + 
2015
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2016
		"----------\n");
2017
}
2018
// a nonnull variable is dereferenced in a finally block inside a loop
2019
public void test_nonnull_var_in_constrol_structure_3() {
2020
	Map customOptions = getCompilerOptions();
2021
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
2022
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
2023
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
2024
	customOptions.put(CompilerOptions.OPTION_ReportRedundantNullAnnotation, CompilerOptions.IGNORE);
2025
	runNegativeTestWithLibs(
2026
		new String[] {
2027
			"X.java",
2028
			"import org.eclipse.jdt.annotation.*;\n" +
2029
			"public class X {\n" +
2030
			"    void print4(@NonNull String s) {\n" +
2031
			"        for (int i=0; i<4; i++)\n" +
2032
			"            try { /*empty*/ } finally {\n" +
2033
			"                 print(s);\n" +
2034
			"            }\n" + 
2035
			"    }\n" +
2036
			"    void print5(@Nullable String s) {\n" +
2037
			"        for (int i=0; i<5; i++)\n" +
2038
			"            try { /*empty*/ } finally {\n" +
2039
			"                 print(s);\n" +
2040
			"            }\n" + 
2041
			"    }\n" +
2042
			"    void print6(boolean b) {\n" +
2043
			"        String s = b ? null : \"\";\n" +
2044
			"        for (int i=0; i<4; i++)\n" +
2045
			"            try { /*empty*/ } finally {\n" +
2046
			"                 print(s);\n" +
2047
			"            }\n" + 
2048
			"    }\n" +
2049
			"    void print(@NonNull String s) {\n" +
2050
			"        System.out.print(s);\n" +
2051
			"    }\n" +
2052
			"}\n",
2053
2054
		},
2055
		customOptions,
2056
		"----------\n" + 
2057
		"1. ERROR in X.java (at line 12)\n" + 
2058
		"	print(s);\n" + 
2059
		"	      ^\n" + 
2060
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2061
		"----------\n" + 
2062
		"2. ERROR in X.java (at line 19)\n" + 
2063
		"	print(s);\n" + 
2064
		"	      ^\n" + 
2065
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2066
		"----------\n");
2067
}
2068
// a nonnull variable is dereferenced method of a nested type
2069
public void test_nesting_1() {
2070
	Map customOptions = getCompilerOptions();
2071
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
2072
	customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, CompilerOptions.ERROR);
2073
	customOptions.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
2074
	runNegativeTestWithLibs(
2075
		new String[] {
2076
			"X.java",
2077
			"import org.eclipse.jdt.annotation.*;\n" +
2078
			"@NonNullByDefault\n" +
2079
			"public class X {\n" +
2080
			"    void print4(final String s1) {\n" +
2081
			"        for (int i=0; i<3; i++)\n" +
2082
			"            new Runnable() {\n" +
2083
			"                public void run() {\n" +
2084
			"                     print(s1);\n" +
2085
			"                }\n" +
2086
			"            }.run();\n" + 
2087
			"    }\n" +
2088
			"    void print8(final @Nullable String s2) {\n" +
2089
			"        for (int i=0; i<3; i++)\n" +
2090
			"            new Runnable() {\n" +
2091
			"                public void run() {\n" +
2092
			"                     print(s2);\n" +
2093
			"                }\n" +
2094
			"            }.run();\n" + 
2095
			"    }\n" +
2096
			"    void print16(boolean b) {\n" +
2097
			"        final String s3 = b ? null : \"\";\n" +
2098
			"        for (int i=0; i<3; i++)\n" +
2099
			"            new Runnable() {\n" +
2100
			"                public void run() {\n" +
2101
			"                     @NonNull String s3R = s3;\n" +
2102
			"                }\n" +
2103
			"            }.run();\n" + 
2104
			"    }\n" +
2105
			"    void print(String s) {\n" +
2106
			"        System.out.print(s);\n" +
2107
			"    }\n" +
2108
			"}\n",
2109
2110
		},
2111
		customOptions,
2112
		"----------\n" + 
2113
		"1. ERROR in X.java (at line 16)\n" + 
2114
		"	print(s2);\n" + 
2115
		"	      ^^\n" + 
2116
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2117
		"----------\n" + 
2118
		"2. ERROR in X.java (at line 25)\n" + 
2119
		"	@NonNull String s3R = s3;\n" + 
2120
		"	                      ^^\n" + 
2121
		"Type mismatch: required \'@NonNull String\' but the provided value can be null\n" + 
2122
		"----------\n");
2123
}
2124
// Test a regression incurred to the OT/J based implementation
2125
// by the fix in Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
2126
public void test_constructor_with_nested_class() {
2127
	runConformTest(
2128
		new String[] {
2129
			"X.java",
2130
			"public class X {\n" +
2131
			"    final Object o1;\n" +
2132
			"    final Object o2;\n" +
2133
			"    public X() {\n" +
2134
			"         this.o1 = new Object() {\n" +
2135
			"             public String toString() { return \"O1\"; }\n" +
2136
			"         };\n" +
2137
			"         this.o2 = new Object();" +
2138
			"    }\n" +
2139
			"}\n"
2140
		},
2141
		"");
2142
}
2143
}
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java (+1 lines)
Lines 96-101 Link Here
96
	since_1_5.add(InnerEmulationTest_1_5.class);
96
	since_1_5.add(InnerEmulationTest_1_5.class);
97
	since_1_5.add(AssignmentTest_1_5.class);
97
	since_1_5.add(AssignmentTest_1_5.class);
98
	since_1_5.add(InnerClass15Test.class);
98
	since_1_5.add(InnerClass15Test.class);
99
	since_1_5.add(NullAnnotationTest.class);
99
100
100
	// Tests to run when compliance is greater than 1.5
101
	// Tests to run when compliance is greater than 1.5
101
	ArrayList since_1_6 = new ArrayList();
102
	ArrayList since_1_6 = new ArrayList();
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java (+32 lines)
Lines 1412-1417 Link Here
1412
	/** @since 3.8 */
1412
	/** @since 3.8 */
1413
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1413
	int SwitchOnEnumNotBelow15 = TypeRelated + 890;	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=360317
1414
	/**
1414
	/**
1415
	 * Errors/warnings from annotation based null analysis
1416
	 */
1417
	/** @since 3.8 */
1418
	int RequiredNonNullButProvidedNull = TypeRelated + 910;
1419
	/** @since 3.8 */
1420
	int RequiredNonNullButProvidedPotentialNull = TypeRelated + 911;
1421
	/** @since 3.8 */
1422
	int RequiredNonNullButProvidedUnknown = TypeRelated + 912;
1423
	/** @since 3.8 */
1424
	int MissingNullAnnotationType = ImportRelated + 913;
1425
	/** @since 3.8 */
1426
	int NullAnnotationNameMustBeQualified = Internal + 914;
1427
	/** @since 3.8 */
1428
	int IllegalReturnNullityRedefinition = MethodRelated + 915;
1429
	/** @since 3.8 */
1430
	int IllegalRedefinitionToNonNullParameter = MethodRelated + 916;
1431
	/** @since 3.8 */
1432
	int IllegalDefinitionToNonNullParameter = MethodRelated + 917;
1433
	/** @since 3.8 */
1434
	int ParameterLackingNonNullAnnotation = MethodRelated + 918;
1435
	/** @since 3.8 */
1436
	int ParameterLackingNullableAnnotation = MethodRelated + 919;
1437
	/** @since 3.8 */
1438
	int PotentialNullMessageSendReference = Internal + 920;
1439
	/** @since 3.8 */
1440
	int RedundantNullCheckOnNonNullMessageSend = Internal + 921;
1441
	/** @since 3.8 */
1442
	int CannotImplementIncompatibleNullness = Internal + 922;
1443
	/** @since 3.8 */
1444
	int RedundantNullAnnotation = MethodRelated + 923;
1445
	
1446
	/**
1415
	 * External problems -- These are problems defined by other plugins
1447
	 * External problems -- These are problems defined by other plugins
1416
	 */
1448
	 */
1417
1449
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (+8 lines)
Lines 254-259 Link Here
254
	// this is only used for method invocation as the expression inside an expression statement
254
	// this is only used for method invocation as the expression inside an expression statement
255
	public static final int InsideExpressionStatement = Bit5;
255
	public static final int InsideExpressionStatement = Bit5;
256
256
257
	// for annotation reference, signal if annotation was created from a default:
258
	public static final int IsSynthetic = ASTNode.Bit7;
259
	// for name reference within a memberValuePair of an annotation:
260
	public static final int IsMemberValueReference = ASTNode.Bit15;
261
262
	// for method declaration to avoid duplicate invocation of bindArguments()
263
	public static final int HasBoundArguments = ASTNode.Bit10; 
264
257
	public ASTNode() {
265
	public ASTNode() {
258
266
259
		super();
267
		super();
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java (-1 / +62 lines)
Lines 10-17 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import java.util.Arrays;
14
13
import org.eclipse.jdt.core.compiler.*;
15
import org.eclipse.jdt.core.compiler.*;
14
import org.eclipse.jdt.internal.compiler.*;
16
import org.eclipse.jdt.internal.compiler.*;
17
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
15
import org.eclipse.jdt.internal.compiler.impl.*;
18
import org.eclipse.jdt.internal.compiler.impl.*;
16
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17
import org.eclipse.jdt.internal.compiler.codegen.*;
20
import org.eclipse.jdt.internal.compiler.codegen.*;
Lines 66-78 Link Here
66
				throw new AbortMethod(this.compilationResult, problem);
69
				throw new AbortMethod(this.compilationResult, problem);
67
		}
70
		}
68
	}
71
	}
72
	
73
	/** 
74
	 * Materialize a null annotation that has been added from the current default,
75
	 * in order to ensure that this annotation will be generated into the .class file, too.
76
	 */
77
	public void addNullnessAnnotation(ReferenceBinding annotationBinding) {
78
		this.annotations = addAnnotation(this, this.annotations, annotationBinding);
79
	}
80
81
	/** 
82
	 * Materialize a null parameter annotation that has been added from the current default,
83
	 * in order to ensure that this annotation will be generated into the .class file, too.
84
	 */
85
	public void addParameterNonNullAnnotation(int i, ReferenceBinding annotationBinding) {
86
		Argument argument = this.arguments[i];
87
		if (argument.type != null) // null happens for constructors of anonymous classes
88
			argument.annotations = addAnnotation(argument.type, argument.annotations, annotationBinding);
89
	}
90
91
	private Annotation[] addAnnotation(ASTNode location, Annotation[] oldAnnotations, ReferenceBinding annotationBinding) {
92
		long pos = ((long)location.sourceStart<<32) + location.sourceEnd;
93
		long[] poss = new long[annotationBinding.compoundName.length];
94
		Arrays.fill(poss, pos);
95
		MarkerAnnotation annotation = new MarkerAnnotation(new QualifiedTypeReference(annotationBinding.compoundName, poss), location.sourceStart);
96
		annotation.declarationSourceEnd = location.sourceEnd;
97
		annotation.resolvedType = annotationBinding;
98
		annotation.bits = IsSynthetic;
99
		if (oldAnnotations == null) {
100
			oldAnnotations = new Annotation[] {annotation};
101
		} else {
102
			int len = oldAnnotations.length;
103
			System.arraycopy(oldAnnotations, 0, oldAnnotations=new Annotation[len+1], 1, len);
104
			oldAnnotations[0] = annotation;
105
		}
106
		return oldAnnotations;
107
	}
69
108
70
	/**
109
	/**
71
	 * Bind and add argument's binding into the scope of the method
110
	 * Bind and add argument's binding into the scope of the method
72
	 */
111
	 */
73
	public void bindArguments() {
112
	public void bindArguments() {
74
113
75
		if (this.arguments != null) {
114
		if (this.arguments != null && (this.bits & HasBoundArguments) == 0) {
115
			this.bits |= HasBoundArguments;
76
			// by default arguments in abstract/native methods are considered to be used (no complaint is expected)
116
			// by default arguments in abstract/native methods are considered to be used (no complaint is expected)
77
			if (this.binding == null) {
117
			if (this.binding == null) {
78
				for (int i = 0, length = this.arguments.length; i < length; i++) {
118
				for (int i = 0, length = this.arguments.length; i < length; i++) {
Lines 85-90 Link Here
85
			for (int i = 0, length = this.arguments.length; i < length; i++) {
125
			for (int i = 0, length = this.arguments.length; i < length; i++) {
86
				Argument argument = this.arguments[i];
126
				Argument argument = this.arguments[i];
87
				argument.bind(this.scope, this.binding.parameters[i], used);
127
				argument.bind(this.scope, this.binding.parameters[i], used);
128
				// argument.bind() has resolved annotations, now transfer nullness info from the argument to the method:
129
				if ((argument.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0) {
130
					if (this.binding.parameterNonNullness == null)
131
						this.binding.parameterNonNullness = new Boolean[this.arguments.length];
132
					this.binding.parameterNonNullness[i] = Boolean.valueOf((argument.binding.tagBits & TagBits.AnnotationNonNull) != 0);
133
				}
88
				if (argument.annotations != null) {
134
				if (argument.annotations != null) {
89
					if (paramAnnotations == null) {
135
					if (paramAnnotations == null) {
90
						paramAnnotations = new AnnotationBinding[length][];
136
						paramAnnotations = new AnnotationBinding[length][];
Lines 143-148 Link Here
143
		}
189
		}
144
	}
190
	}
145
191
192
	void analyseArgumentNullity(FlowInfo info) {
193
		if (this.arguments != null && this.binding.parameterNonNullness != null) {
194
			for (int i = 0, count = this.arguments.length; i < count; i++) {
195
				// leverage null-info from parameter annotations:
196
				Boolean nonNullNess = this.binding.parameterNonNullness[i];
197
				if (nonNullNess != null) {
198
					if (nonNullNess.booleanValue())
199
						info.markAsDefinitelyNonNull(this.arguments[i].binding);
200
					else
201
						info.markPotentiallyNullBit(this.arguments[i].binding);
202
				}
203
			}
204
		}
205
	}
206
146
	public CompilationResult compilationResult() {
207
	public CompilationResult compilationResult() {
147
208
148
		return this.compilationResult;
209
		return this.compilationResult;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (+1 lines)
Lines 53-58 Link Here
53
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
53
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
54
			}
54
			}
55
		}
55
		}
56
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
56
	}
57
	}
57
	// record some dependency information for exception types
58
	// record some dependency information for exception types
58
	ReferenceBinding[] thrownExceptions;
59
	ReferenceBinding[] thrownExceptions;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java (+16 lines)
Lines 173-178 Link Here
173
			case TypeIds.T_JavaxAnnotationPreDestroy :
173
			case TypeIds.T_JavaxAnnotationPreDestroy :
174
				tagBits |= TagBits.AnnotationPreDestroy;
174
				tagBits |= TagBits.AnnotationPreDestroy;
175
				break;
175
				break;
176
			case TypeIds.T_ConfiguredAnnotationNullable :
177
				tagBits |= TagBits.AnnotationNullable;
178
				break;
179
			case TypeIds.T_ConfiguredAnnotationNonNull :
180
				tagBits |= TagBits.AnnotationNonNull;
181
				break;
182
			case TypeIds.T_ConfiguredAnnotationNonNullByDefault :
183
				if (valueAttribute != null 
184
					&& valueAttribute.value instanceof FalseLiteral) 
185
				{
186
					// parameter 'false' means: this annotation cancels any defaults
187
					tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
188
					break;
189
				}
190
				tagBits |= TagBits.AnnotationNonNullByDefault;
191
				break;
176
		}
192
		}
177
		return tagBits;
193
		return tagBits;
178
	}
194
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-1 / +1 lines)
Lines 65-71 Link Here
65
				FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
65
				FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
66
		}
66
		}
67
	}
67
	}
68
	nullStatus = checkAgainstNullAnnotation(currentScope, local, nullStatus);
68
	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, local, nullStatus, this.expression);
69
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
69
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
70
		flowInfo.markNullStatus(local, nullStatus);
70
		flowInfo.markNullStatus(local, nullStatus);
71
		if (flowContext.initsOnFinally != null)
71
		if (flowContext.initsOnFinally != null)
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (-1 / +11 lines)
Lines 113-121 Link Here
113
			}
113
			}
114
		}
114
		}
115
115
116
		// tag parameters as being set
117
		if (this.arguments != null) {
116
		if (this.arguments != null) {
118
			for (int i = 0, count = this.arguments.length; i < count; i++) {
117
			for (int i = 0, count = this.arguments.length; i < count; i++) {
118
				if (this.binding.parameterNonNullness != null) {
119
					// leverage null-info from parameter annotations:
120
					Boolean nonNullNess = this.binding.parameterNonNullness[i];
121
					if (nonNullNess != null) {
122
						if (nonNullNess.booleanValue())
123
							flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
124
						else
125
							flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
126
					}
127
				}
128
				// tag parameters as being set
119
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
129
				flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
120
			}
130
			}
121
		}
131
		}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java (-1 / +16 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 23-28 Link Here
23
		super(left,right,operator);
23
		super(left,right,operator);
24
	}
24
	}
25
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
25
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
26
		// check sends to null-annotated methods:
27
		MessageSend leftMessage = (this.left instanceof MessageSend) ? (MessageSend) this.left : null;
28
		if (   leftMessage != null 
29
			&& leftMessage.nullStatus(flowInfo) == FlowInfo.NON_NULL
30
			&& this.right.nullStatus(flowInfo) == FlowInfo.NULL) 
31
		{
32
			scope.problemReporter().messageSendRedundantCheckOnNonNull(leftMessage.binding, leftMessage);
33
		}
34
		MessageSend rightMessage = (this.right instanceof MessageSend) ? (MessageSend) this.right : null;
35
		if (   rightMessage != null 
36
			&& rightMessage.nullStatus(flowInfo) == FlowInfo.NON_NULL 
37
			&& this.left.nullStatus(flowInfo) == FlowInfo.NULL) 
38
		{
39
			scope.problemReporter().messageSendRedundantCheckOnNonNull(rightMessage.binding, rightMessage);
40
		}
26
41
27
		LocalVariableBinding local = this.left.localVariableBinding();
42
		LocalVariableBinding local = this.left.localVariableBinding();
28
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
43
		if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java (+1 lines)
Lines 81-86 Link Here
81
						this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
81
						this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
82
					}
82
					}
83
				}
83
				}
84
				analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
84
			}
85
			}
85
86
86
			ReferenceBinding[] thrownExceptions;
87
			ReferenceBinding[] thrownExceptions;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-1 / +1 lines)
Lines 85-91 Link Here
85
		this.bits &= ~FirstAssignmentToLocal;  // int i = (i = 0);
85
		this.bits &= ~FirstAssignmentToLocal;  // int i = (i = 0);
86
	}
86
	}
87
	flowInfo.markAsDefinitelyAssigned(this.binding);
87
	flowInfo.markAsDefinitelyAssigned(this.binding);
88
	nullStatus = checkAgainstNullAnnotation(currentScope, this.binding, nullStatus);		
88
	nullStatus = checkAssignmentAgainstNullAnnotation(currentScope, flowContext, this.binding, nullStatus, this.initialization);		
89
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
89
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
90
		flowInfo.markNullStatus(this.binding, nullStatus);
90
		flowInfo.markNullStatus(this.binding, nullStatus);
91
		// no need to inform enclosing try block since its locals won't get
91
		// no need to inform enclosing try block since its locals won't get
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.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 41-46 Link Here
41
		if (value instanceof ArrayInitializer) {
41
		if (value instanceof ArrayInitializer) {
42
			value.bits |= IsAnnotationDefaultValue;
42
			value.bits |= IsAnnotationDefaultValue;
43
		}
43
		}
44
		if (value instanceof NameReference) {
45
			value.bits |= IsMemberValueReference;
46
		}
44
	}
47
	}
45
48
46
	/* (non-Javadoc)
49
	/* (non-Javadoc)
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-1 / +14 lines)
Lines 99-104 Link Here
99
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
99
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
100
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
100
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
		}
101
		}
102
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
102
	}
103
	}
103
	ReferenceBinding[] thrownExceptions;
104
	ReferenceBinding[] thrownExceptions;
104
	if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
105
	if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
Lines 114-119 Link Here
114
	}
115
	}
115
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
116
	manageSyntheticAccessIfNecessary(currentScope, flowInfo);
116
	return flowInfo;
117
	return flowInfo;
118
}
119
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
120
	super.checkNPE(scope, flowContext, flowInfo);
121
	if (nullStatus(flowInfo) == FlowInfo.POTENTIALLY_NULL)
122
		scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
117
}
123
}
118
/**
124
/**
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)
125
 * @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
	}
274
	}
269
}
275
}
270
public int nullStatus(FlowInfo flowInfo) {
276
public int nullStatus(FlowInfo flowInfo) {
277
	if (this.binding.isValidBinding()) {
278
		// try to retrieve null status of this message send from an annotation of the called method:
279
		long tagBits = this.binding.tagBits;
280
		if ((tagBits & TagBits.AnnotationNonNull) != 0)
281
			return FlowInfo.NON_NULL;
282
		if ((tagBits & TagBits.AnnotationNullable) != 0)
283
			return FlowInfo.POTENTIALLY_NULL;
284
	}
271
	return FlowInfo.UNKNOWN;
285
	return FlowInfo.UNKNOWN;
272
}
286
}
273
274
/**
287
/**
275
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
288
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
276
 */
289
 */
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (-1 / +11 lines)
Lines 79-87 Link Here
79
					this.scope,
79
					this.scope,
80
					FlowInfo.DEAD_END);
80
					FlowInfo.DEAD_END);
81
81
82
			// tag parameters as being set
83
			if (this.arguments != null) {
82
			if (this.arguments != null) {
84
				for (int i = 0, count = this.arguments.length; i < count; i++) {
83
				for (int i = 0, count = this.arguments.length; i < count; i++) {
84
					if (this.binding.parameterNonNullness != null) {
85
						// leverage null-info from parameter annotations:
86
						Boolean nonNullNess = this.binding.parameterNonNullness[i];
87
						if (nonNullNess != null) {
88
							if (nonNullNess.booleanValue())
89
								flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
90
							else
91
								flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
92
						}
93
					}
94
					// tag parameters as being set:
85
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
95
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
86
					// if this method uses a type parameter declared by the declaring class,
96
					// 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
97
					// it can't be static. https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (+1 lines)
Lines 86-91 Link Here
86
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
86
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
87
				}
87
				}
88
			}
88
			}
89
			analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
89
		}
90
		}
90
91
91
		// analyse the anonymous nested type
92
		// analyse the anonymous nested type
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-1 / +5 lines)
Lines 963-969 Link Here
963
							&& methodScope.lastVisibleFieldID >= 0
963
							&& methodScope.lastVisibleFieldID >= 0
964
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
964
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
965
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
965
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
966
						scope.problemReporter().forwardReference(this, this.indexOfFirstFieldBinding-1, fieldBinding);
966
						if ((this.bits & IsMemberValueReference) != 0 && fieldBinding.id == methodScope.lastVisibleFieldID) {
967
							// false alarm, location is NOT a field initializer but the value in a memberValuePair
968
						} else {
969
							scope.problemReporter().forwardReference(this, this.indexOfFirstFieldBinding-1, fieldBinding);
970
						}
967
					}
971
					}
968
					if (isFieldUseDeprecated(fieldBinding, scope, this.indexOfFirstFieldBinding == this.tokens.length ? this.bits : 0)) {
972
					if (isFieldUseDeprecated(fieldBinding, scope, this.indexOfFirstFieldBinding == this.tokens.length ? this.bits : 0)) {
969
						scope.problemReporter().deprecatedField(fieldBinding, this);	
973
						scope.problemReporter().deprecatedField(fieldBinding, this);	
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (+19 lines)
Lines 44-49 Link Here
44
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
44
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
45
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
45
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
46
		}
46
		}
47
		if (flowInfo.reachMode() == FlowInfo.REACHABLE)
48
			checkAgainstNullAnnotation(currentScope, this.expression.nullStatus(flowInfo));
47
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression);
49
		FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression);
48
		if (trackingVariable != null) {
50
		if (trackingVariable != null) {
49
			if (methodScope != trackingVariable.methodScope)
51
			if (methodScope != trackingVariable.methodScope)
Lines 119-124 Link Here
119
	currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
121
	currentScope.checkUnclosedCloseables(flowInfo, this, currentScope);
120
	return FlowInfo.DEAD_END;
122
	return FlowInfo.DEAD_END;
121
}
123
}
124
void checkAgainstNullAnnotation(BlockScope scope, int nullStatus) {
125
	if (nullStatus != FlowInfo.NON_NULL) {
126
		// if we can't prove non-null check against declared null-ness of the enclosing method:
127
		long tagBits;
128
		MethodBinding methodBinding;
129
		try {
130
			methodBinding = scope.methodScope().referenceMethod().binding;
131
			tagBits = methodBinding.tagBits;
132
		} catch (NullPointerException npe) {
133
			return;
134
		}
135
		if ((tagBits & TagBits.AnnotationNonNull) != 0) {
136
			char[][] annotationName = scope.environment().getNonNullAnnotationName();
137
			scope.problemReporter().nullityMismatch(this.expression, methodBinding.returnType, nullStatus, annotationName);
138
		}
139
	}
140
}
122
141
123
/**
142
/**
124
 * Retrun statement code generation
143
 * Retrun statement code generation
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java (-2 / +29 lines)
Lines 57-64 Link Here
57
	public static final int COMPLAINED_FAKE_REACHABLE = 1;
57
	public static final int COMPLAINED_FAKE_REACHABLE = 1;
58
	public static final int COMPLAINED_UNREACHABLE = 2;
58
	public static final int COMPLAINED_UNREACHABLE = 2;
59
	
59
	
60
/** Empty hook for checking null status against declaration using null annotations, once this will be supported. */
60
61
protected int checkAgainstNullAnnotation(BlockScope currentScope, LocalVariableBinding local, int nullStatus) {
61
/** Analysing arguments of MessageSend, ExplicitConstructorCall, AllocationExpression. */
62
protected void analyseArguments(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, MethodBinding methodBinding, Expression[] arguments) 
63
{
64
	// compare actual null-status against parameter annotations of the called method:
65
	if (arguments != null && methodBinding.parameterNonNullness != null) {
66
		for (int i = 0; i < arguments.length; i++) {
67
			if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) { 
68
				TypeBinding expectedType = methodBinding.parameters[i];
69
				Expression argument = arguments[i];
70
				int nullStatus = argument.nullStatus(flowInfo); // slight loss of precision: should also use the null info from the receiver.
71
				if (nullStatus != FlowInfo.NON_NULL) // if required non-null is not provided
72
					flowContext.recordNullityMismatch(currentScope, argument, nullStatus, expectedType);
73
			}
74
		}
75
	}
76
}
77
78
/** Check null-ness of 'local' against a possible null annotation */
79
protected int checkAssignmentAgainstNullAnnotation(BlockScope currentScope, FlowContext flowContext,
80
												   LocalVariableBinding local, int nullStatus, Expression expression)
81
{
82
	if (   local != null
83
		&& (local.tagBits & TagBits.AnnotationNonNull) != 0 
84
		&& nullStatus != FlowInfo.NON_NULL)
85
	{
86
		flowContext.recordNullityMismatch(currentScope, expression, nullStatus, local.type);
87
		nullStatus=FlowInfo.NON_NULL;
88
	}
62
	return nullStatus;
89
	return nullStatus;
63
}
90
}
64
91
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java (-2 / +25 lines)
Lines 17-22 Link Here
17
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
17
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.Scope;
19
import org.eclipse.jdt.internal.compiler.lookup.Scope;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
21
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
21
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
22
23
Lines 83-90 Link Here
83
	// check inconsistent null checks
84
	// check inconsistent null checks
84
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
85
	if ((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) { // within an enclosing loop, be conservative
85
		for (int i = 0; i < this.nullCount; i++) {
86
		for (int i = 0; i < this.nullCount; i++) {
86
			this.parent.recordUsingNullReference(scope, this.nullLocals[i],
87
			if (this.nullCheckTypes[i] == ASSIGN_TO_NONNULL)
87
					this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
88
				this.parent.recordNullityMismatch(scope, this.nullReferences[i], 
89
						flowInfo.nullStatus(this.nullLocals[i]), this.expectedTypes[i]);
90
			else
91
				this.parent.recordUsingNullReference(scope, this.nullLocals[i],
92
						this.nullReferences[i],	this.nullCheckTypes[i], flowInfo);
93
			
88
		}
94
		}
89
	}
95
	}
90
	else { // no enclosing loop, be as precise as possible right now
96
	else { // no enclosing loop, be as precise as possible right now
Lines 165-170 Link Here
165
					}
171
					}
166
					if (flowInfo.isPotentiallyNull(local)) {
172
					if (flowInfo.isPotentiallyNull(local)) {
167
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
173
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
174
					}
175
					break;
176
				case ASSIGN_TO_NONNULL:
177
					int nullStatus = flowInfo.nullStatus(local);
178
					if (nullStatus != FlowInfo.NON_NULL) {
179
						char[][] annotationName = scope.environment().getNonNullAnnotationName();
180
						scope.problemReporter().nullityMismatch(expression, this.expectedTypes[i], nullStatus, annotationName);
168
					}
181
					}
169
					break;
182
					break;
170
				default:
183
				default:
Lines 442-445 Link Here
442
	this.nullReferences[this.nullCount] = expression;
455
	this.nullReferences[this.nullCount] = expression;
443
	this.nullCheckTypes[this.nullCount++] = status;
456
	this.nullCheckTypes[this.nullCount++] = status;
444
}
457
}
458
protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
459
	// cf. decision structure inside FinallyFlowContext.recordUsingNullReference(..)
460
	if (nullStatus == FlowInfo.UNKNOWN ||
461
			((this.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0 && nullStatus != FlowInfo.NULL)) {
462
		recordExpectedType(expectedType, this.nullCount);
463
		recordNullReference(expression.localVariableBinding(), expression, checkType);
464
		return true;
465
	}
466
	return false;
467
}
445
}
468
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (+48 lines)
Lines 52-57 Link Here
52
		// any null related operation happening within the try block
52
		// any null related operation happening within the try block
53
53
54
	public int tagBits;
54
	public int tagBits;
55
	
56
	// array to store the expected type from the potential error location (for display in error messages):
57
	public TypeBinding[] expectedTypes = null;
58
	
55
	public static final int DEFER_NULL_DIAGNOSTIC = 0x1;
59
	public static final int DEFER_NULL_DIAGNOSTIC = 0x1;
56
	public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2;
60
	public static final int PREEMPT_NULL_DIAGNOSTIC = 0x2;
57
	/**
61
	/**
Lines 66-71 Link Here
66
public static final int CAN_ONLY_NON_NULL = 0x0002;
70
public static final int CAN_ONLY_NON_NULL = 0x0002;
67
//check against non null, with definite values -- comparisons
71
//check against non null, with definite values -- comparisons
68
public static final int MAY_NULL = 0x0003;
72
public static final int MAY_NULL = 0x0003;
73
//check binding a value to a @NonNull variable 
74
public final static int ASSIGN_TO_NONNULL = 0x0080;
69
// check against null, with potential values -- NPE guard
75
// check against null, with potential values -- NPE guard
70
public static final int CHECK_MASK = 0x00FF;
76
public static final int CHECK_MASK = 0x00FF;
71
public static final int IN_COMPARISON_NULL = 0x0100;
77
public static final int IN_COMPARISON_NULL = 0x0100;
Lines 548-553 Link Here
548
	// default implementation: do nothing
554
	// default implementation: do nothing
549
}
555
}
550
556
557
protected void recordExpectedType(TypeBinding expectedType, int nullCount) {
558
	if (nullCount == 0) {
559
		this.expectedTypes = new TypeBinding[5];
560
	} else if (this.expectedTypes == null) {
561
		int size = 5;
562
		while (size <= nullCount) size *= 2;
563
		this.expectedTypes = new TypeBinding[size];
564
	}
565
	else if (nullCount == this.expectedTypes.length) {
566
		System.arraycopy(this.expectedTypes, 0,
567
			this.expectedTypes = new TypeBinding[nullCount * 2], 0, nullCount);
568
	}
569
	this.expectedTypes[nullCount] = expectedType;
570
}
571
551
protected boolean recordFinalAssignment(VariableBinding variable, Reference finalReference) {
572
protected boolean recordFinalAssignment(VariableBinding variable, Reference finalReference) {
552
	return true; // keep going
573
	return true; // keep going
553
}
574
}
Lines 746-749 Link Here
746
	buffer.append(individualToString()).append('\n');
767
	buffer.append(individualToString()).append('\n');
747
	return buffer.toString();
768
	return buffer.toString();
748
}
769
}
770
771
/**
772
 * Record that a nullity mismatch was detected against an annotated type reference.
773
 * @param currentScope scope for error reporting
774
 * @param expression the expression violating the specification
775
 * @param nullStatus the null status of expression at the current location
776
 * @param expectedType the declared type of the spec'ed variable, for error reporting.
777
 */
778
public void recordNullityMismatch(BlockScope currentScope, Expression expression, int nullStatus, TypeBinding expectedType) {
779
	if (expression.localVariableBinding() != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields)
780
		// find the inner-most flowContext that might need deferred handling:
781
		FlowContext currentContext = this;
782
		while (currentContext != null) {
783
			// some flow contexts implement deferred checking, should we participate in that?
784
			if (currentContext.internalRecordNullityMismatch(expression, nullStatus, expectedType, ASSIGN_TO_NONNULL))										
785
				return;
786
			currentContext = currentContext.parent;
787
		}
788
	}			
789
	// no reason to defer, so report now:
790
	char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
791
	currentScope.problemReporter().nullityMismatch(expression, expectedType, nullStatus, annotationName);
792
}
793
protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
794
	// nop, to be overridden in subclasses
795
	return false; // not recorded
796
}
749
}
797
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (+18 lines)
Lines 12-17 Link Here
12
package org.eclipse.jdt.internal.compiler.flow;
12
package org.eclipse.jdt.internal.compiler.flow;
13
13
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
15
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
16
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
17
import org.eclipse.jdt.internal.compiler.ast.Expression;
17
import org.eclipse.jdt.internal.compiler.ast.Reference;
18
import org.eclipse.jdt.internal.compiler.ast.Reference;
Lines 21-26 Link Here
21
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.Scope;
24
import org.eclipse.jdt.internal.compiler.lookup.Scope;
25
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
26
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
25
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
26
28
Lines 246-251 Link Here
246
						continue;
248
						continue;
247
					}
249
					}
248
					break;
250
					break;
251
				case ASSIGN_TO_NONNULL:
252
					this.parent.recordNullityMismatch(scope, expression, flowInfo.nullStatus(local), this.expectedTypes[i]);
253
					break;
249
				default:
254
				default:
250
					// never happens
255
					// never happens
251
			}
256
			}
Lines 337-342 Link Here
337
						this.nullReferences[i] = null;
342
						this.nullReferences[i] = null;
338
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
343
						scope.problemReporter().localVariablePotentialNullReference(local, expression);
339
						continue;
344
						continue;
345
					}
346
					break;
347
				case ASSIGN_TO_NONNULL:
348
					int nullStatus = flowInfo.nullStatus(local);
349
					if (nullStatus != FlowInfo.NON_NULL) {
350
						char[][] annotationName = scope.environment().getNonNullAnnotationName();
351
						scope.problemReporter().nullityMismatch(expression, this.expectedTypes[i], nullStatus, annotationName);
340
					}
352
					}
341
					break;
353
					break;
342
				default:
354
				default:
Lines 667-670 Link Here
667
	public boolean hasEscapingExceptions() {
679
	public boolean hasEscapingExceptions() {
668
		return this.escapingExceptionCatchSites != null;
680
		return this.escapingExceptionCatchSites != null;
669
	}
681
	}
682
683
	protected boolean internalRecordNullityMismatch(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
684
		recordExpectedType(expectedType, this.nullCount);
685
		recordNullReference(expression.localVariableBinding(), expression, checkType);
686
		return true;
687
	}
670
}
688
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java (-4 / +108 lines)
Lines 26-31 Link Here
26
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
26
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
28
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
29
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
29
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
30
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
30
import org.eclipse.jdt.internal.compiler.util.Util;
31
import org.eclipse.jdt.internal.compiler.util.Util;
31
32
Lines 142-147 Link Here
142
	public static final String OPTION_ReportUnclosedCloseable = "org.eclipse.jdt.core.compiler.problem.unclosedCloseable"; //$NON-NLS-1$
143
	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$
144
	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$
145
	public static final String OPTION_ReportExplicitlyClosedAutoCloseable = "org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable"; //$NON-NLS-1$
146
	public static final String OPTION_ReportNullSpecViolation = "org.eclipse.jdt.core.compiler.problem.nullSpecViolation";  //$NON-NLS-1$
147
	public static final String OPTION_ReportPotentialNullSpecViolation = "org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation";  //$NON-NLS-1$
148
	public static final String OPTION_ReportNullSpecInsufficientInfo = "org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo";  //$NON-NLS-1$
149
	public static final String OPTION_ReportRedundantNullAnnotation = "org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation";  //$NON-NLS-1$
150
	public static final String OPTION_AnnotationBasedNullAnalysis = "org.eclipse.jdt.core.compiler.annotation.nullanalysis"; //$NON-NLS-1$
151
	public static final String OPTION_NullableAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nullable"; //$NON-NLS-1$
152
	public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$
153
	public static final String OPTION_NonNullByDefaultAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnullbydefault"; //$NON-NLS-1$
154
	// defaults for the above:
155
	static final char[][] DEFAULT_NULLABLE_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.Nullable".toCharArray()); //$NON-NLS-1$
156
	static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$
157
	static final char[][] DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNullByDefault".toCharArray()); //$NON-NLS-1$
158
	public static final String OPTION_NonNullIsDefault = "org.eclipse.jdt.core.compiler.annotation.nonnullisdefault";  //$NON-NLS-1$
145
	/**
159
	/**
146
	 * Possible values for configurable options
160
	 * Possible values for configurable options
147
	 */
161
	 */
Lines 245-254 Link Here
245
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
259
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
246
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
260
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
247
	public static final int RedundantSpecificationOfTypeArguments = IrritantSet.GROUP2 | ASTNode.Bit7;
261
	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
262
	public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit8;
249
	public static final int UnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit11;
263
	public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit9;
250
	public static final int PotentiallyUnclosedCloseable = IrritantSet.GROUP2 | ASTNode.Bit12;
264
	public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit10;
251
	public static final int ExplicitlyClosedAutoCloseable = IrritantSet.GROUP2 | ASTNode.Bit13;
265
	public static final int NullSpecViolation = IrritantSet.GROUP2 | ASTNode.Bit11;
266
	public static final int PotentialNullSpecViolation = IrritantSet.GROUP2 | ASTNode.Bit12;
267
	public static final int NullSpecInsufficientInfo = IrritantSet.GROUP2 | ASTNode.Bit13;
268
	public static final int RedundantNullAnnotation = IrritantSet.GROUP2 | ASTNode.Bit14;
252
269
253
	// Severity level for handlers
270
	// Severity level for handlers
254
	/** 
271
	/** 
Lines 370-375 Link Here
370
	public boolean includeNullInfoFromAsserts;
387
	public boolean includeNullInfoFromAsserts;
371
	/** Controls whether forced generic type problems get reported  */
388
	/** Controls whether forced generic type problems get reported  */
372
	public boolean reportUnavoidableGenericTypeProblems;
389
	public boolean reportUnavoidableGenericTypeProblems;
390
391
	// === Support for Null Annotations: ===
392
	/** Master switch for null analysis based on annotations: */
393
	public boolean isAnnotationBasedNullAnalysisEnabled;
394
	/** Fully qualified name of annotation to use as marker for nullable types. */
395
	public char[][] nullableAnnotationName;
396
	/** Fully qualified name of annotation to use as marker for nonnull types. */
397
	public char[][] nonNullAnnotationName;
398
	/** Fully qualified name of annotation to use as marker for default nonnull. */
399
	public char[][] nonNullByDefaultAnnotationName;
400
	/** TagBits-encoded default for non-annotated types. */
401
	public long defaultNonNullness; // 0 or TagBits#AnnotationNonNull
373
402
374
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
403
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
375
	public final static String[] warningTokens = {
404
	public final static String[] warningTokens = {
Lines 567-572 Link Here
567
				return OPTION_ReportPotentiallyUnclosedCloseable;
596
				return OPTION_ReportPotentiallyUnclosedCloseable;
568
			case ExplicitlyClosedAutoCloseable :
597
			case ExplicitlyClosedAutoCloseable :
569
				return OPTION_ReportExplicitlyClosedAutoCloseable;
598
				return OPTION_ReportExplicitlyClosedAutoCloseable;
599
			case NullSpecViolation :
600
				return OPTION_ReportNullSpecViolation;
601
			case PotentialNullSpecViolation :
602
				return OPTION_ReportPotentialNullSpecViolation;
603
			case NullSpecInsufficientInfo :
604
				return OPTION_ReportNullSpecInsufficientInfo;
605
			case RedundantNullAnnotation :
606
				return OPTION_ReportRedundantNullAnnotation;
570
		}
607
		}
571
		return null;
608
		return null;
572
	}
609
	}
Lines 795-800 Link Here
795
			case NullReference :
832
			case NullReference :
796
			case PotentialNullReference :
833
			case PotentialNullReference :
797
			case RedundantNullCheck :
834
			case RedundantNullCheck :
835
			case NullSpecViolation :
836
			case PotentialNullSpecViolation :
837
			case NullSpecInsufficientInfo :
838
			case RedundantNullAnnotation :
798
				return "null"; //$NON-NLS-1$
839
				return "null"; //$NON-NLS-1$
799
			case FallthroughCase :
840
			case FallthroughCase :
800
				return "fallthrough"; //$NON-NLS-1$
841
				return "fallthrough"; //$NON-NLS-1$
Lines 1008-1013 Link Here
1008
		optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
1049
		optionsMap.put(OPTION_ReportUnclosedCloseable, getSeverityString(UnclosedCloseable));
1009
		optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
1050
		optionsMap.put(OPTION_ReportPotentiallyUnclosedCloseable, getSeverityString(PotentiallyUnclosedCloseable));
1010
		optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
1051
		optionsMap.put(OPTION_ReportExplicitlyClosedAutoCloseable, getSeverityString(ExplicitlyClosedAutoCloseable));
1052
		optionsMap.put(OPTION_AnnotationBasedNullAnalysis, this.isAnnotationBasedNullAnalysisEnabled ? ENABLED : DISABLED);
1053
		if (this.isAnnotationBasedNullAnalysisEnabled) {
1054
			optionsMap.put(OPTION_ReportNullSpecViolation, getSeverityString(NullSpecViolation));
1055
			optionsMap.put(OPTION_ReportPotentialNullSpecViolation, getSeverityString(PotentialNullSpecViolation));
1056
			optionsMap.put(OPTION_ReportNullSpecInsufficientInfo, getSeverityString(NullSpecInsufficientInfo));
1057
			optionsMap.put(OPTION_ReportRedundantNullAnnotation, getSeverityString(RedundantNullAnnotation));
1058
			if (this.nullableAnnotationName != null) {
1059
				char[] compoundName = CharOperation.concatWith(this.nullableAnnotationName, '.');
1060
				optionsMap.put(OPTION_NullableAnnotationName, String.valueOf(compoundName));
1061
			}
1062
			if (this.nonNullAnnotationName != null) {
1063
				char[] compoundName = CharOperation.concatWith(this.nonNullAnnotationName, '.');
1064
				optionsMap.put(OPTION_NonNullAnnotationName, String.valueOf(compoundName));
1065
			}
1066
			if (this.nonNullByDefaultAnnotationName != null) {
1067
				char[] compoundName = CharOperation.concatWith(this.nonNullByDefaultAnnotationName, '.');
1068
				optionsMap.put(OPTION_NonNullByDefaultAnnotationName, String.valueOf(compoundName));
1069
			}
1070
			if (this.defaultNonNullness == TagBits.AnnotationNonNull)
1071
				optionsMap.put(OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
1072
			else
1073
				optionsMap.put(OPTION_NonNullIsDefault, CompilerOptions.DISABLED);
1074
		}
1011
		return optionsMap;
1075
		return optionsMap;
1012
	}
1076
	}
1013
1077
Lines 1441-1446 Link Here
1441
		if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
1505
		if ((optionValue = optionsMap.get(OPTION_ReportUnclosedCloseable)) != null) updateSeverity(UnclosedCloseable, optionValue);
1442
		if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
1506
		if ((optionValue = optionsMap.get(OPTION_ReportPotentiallyUnclosedCloseable)) != null) updateSeverity(PotentiallyUnclosedCloseable, optionValue);
1443
		if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
1507
		if ((optionValue = optionsMap.get(OPTION_ReportExplicitlyClosedAutoCloseable)) != null) updateSeverity(ExplicitlyClosedAutoCloseable, optionValue);
1508
		if ((optionValue = optionsMap.get(OPTION_AnnotationBasedNullAnalysis)) != null) {
1509
			if (ENABLED.equals(optionValue)) {
1510
				this.isAnnotationBasedNullAnalysisEnabled = true;
1511
				// ensure that we actually have annotation names to use:
1512
				ensureNullAnnotationNames();
1513
			} else if (DISABLED.equals(optionValue)) {
1514
				this.isAnnotationBasedNullAnalysisEnabled = false;
1515
			}
1516
		}
1517
		if (this.isAnnotationBasedNullAnalysisEnabled) {
1518
			if ((optionValue = optionsMap.get(OPTION_ReportNullSpecViolation)) != null) updateSeverity(NullSpecViolation, optionValue);
1519
			if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullSpecViolation)) != null) updateSeverity(PotentialNullSpecViolation, optionValue);
1520
			if ((optionValue = optionsMap.get(OPTION_ReportNullSpecInsufficientInfo)) != null) updateSeverity(NullSpecInsufficientInfo, optionValue);
1521
			if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullAnnotation)) != null) updateSeverity(RedundantNullAnnotation, optionValue);
1522
			if ((optionValue = optionsMap.get(OPTION_NullableAnnotationName)) != null) {
1523
				this.nullableAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1524
			}
1525
			if ((optionValue = optionsMap.get(OPTION_NonNullAnnotationName)) != null) {
1526
				this.nonNullAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1527
			}
1528
			if ((optionValue = optionsMap.get(OPTION_NonNullByDefaultAnnotationName)) != null) {
1529
				this.nonNullByDefaultAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1530
			}
1531
			if ((optionValue = optionsMap.get(OPTION_NonNullIsDefault)) != null) {
1532
				if (CompilerOptions.ENABLED.equals(optionValue)) {
1533
					this.defaultNonNullness = TagBits.AnnotationNonNull;
1534
					ensureNullAnnotationNames();
1535
				} else {
1536
					this.defaultNonNullness = 0;
1537
				}
1538
			}
1539
		}
1444
1540
1445
		// Javadoc options
1541
		// Javadoc options
1446
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
1542
		if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
Lines 1554-1559 Link Here
1554
			}
1650
			}
1555
		}
1651
		}
1556
	}
1652
	}
1653
	private void ensureNullAnnotationNames() {
1654
		if (this.nullableAnnotationName == null)
1655
			this.nullableAnnotationName = CompilerOptions.DEFAULT_NULLABLE_ANNOTATION_NAME;
1656
		if (this.nonNullAnnotationName == null)
1657
			this.nonNullAnnotationName = CompilerOptions.DEFAULT_NONNULL_ANNOTATION_NAME;
1658
		if (this.nonNullByDefaultAnnotationName == null)
1659
			this.nonNullByDefaultAnnotationName = CompilerOptions.DEFAULT_NONNULLBYDEFAULT_ANNOTATION_NAME;
1660
	}
1557
	public String toString() {
1661
	public String toString() {
1558
		StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
1662
		StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
1559
		buf.append("\n\t- local variables debug attributes: ").append((this.produceDebugAttributes & ClassFileConstants.ATTR_VARS) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1663
		buf.append("\n\t- local variables debug attributes: ").append((this.produceDebugAttributes & ClassFileConstants.ATTR_VARS) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java (-3 / +14 lines)
Lines 102-109 Link Here
102
			.set(
102
			.set(
103
				CompilerOptions.DeadCode
103
				CompilerOptions.DeadCode
104
				|CompilerOptions.Tasks
104
				|CompilerOptions.Tasks
105
				|CompilerOptions.UnclosedCloseable);
105
				|CompilerOptions.UnclosedCloseable
106
			
106
				|CompilerOptions.NullSpecInsufficientInfo
107
				|CompilerOptions.RedundantNullAnnotation);
108
		// default errors IF AnnotationBasedNullAnalysis is enabled:
109
		COMPILER_DEFAULT_ERRORS.set(
110
				CompilerOptions.NullSpecViolation
111
				|CompilerOptions.PotentialNullSpecViolation);
112
107
		ALL.setAll();
113
		ALL.setAll();
108
		HIDING
114
		HIDING
109
			.set(CompilerOptions.FieldHiding)
115
			.set(CompilerOptions.FieldHiding)
Lines 111-117 Link Here
111
			.set(CompilerOptions.TypeHiding);
117
			.set(CompilerOptions.TypeHiding);
112
		NULL
118
		NULL
113
			.set(CompilerOptions.PotentialNullReference)
119
			.set(CompilerOptions.PotentialNullReference)
114
			.set(CompilerOptions.RedundantNullCheck);
120
			.set(CompilerOptions.RedundantNullCheck)
121
			.set(CompilerOptions.NullSpecViolation)
122
			.set(CompilerOptions.PotentialNullSpecViolation)
123
			.set(CompilerOptions.NullSpecInsufficientInfo)
124
			.set(CompilerOptions.RedundantNullAnnotation);
125
115
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
126
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
116
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
127
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
117
		UNUSED
128
		UNUSED
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (+96 lines)
Lines 16-21 Link Here
16
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
17
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.env.*;
18
import org.eclipse.jdt.internal.compiler.env.*;
19
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
19
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
21
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
21
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
22
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
Lines 383-388 Link Here
383
		}
384
		}
384
		if (this.environment.globalOptions.storeAnnotations)
385
		if (this.environment.globalOptions.storeAnnotations)
385
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
386
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
387
		
388
		scanTypeForNullAnnotation(binaryType);
386
	} finally {
389
	} finally {
387
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
390
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
388
		if (this.fields == null)
391
		if (this.fields == null)
Lines 589-594 Link Here
589
	// fixup the declaring element of the type variable
592
	// fixup the declaring element of the type variable
590
	for (int i = 0, length = typeVars.length; i < length; i++)
593
	for (int i = 0, length = typeVars.length; i < length; i++)
591
		typeVars[i].declaringElement = result;
594
		typeVars[i].declaringElement = result;
595
	
596
	scanMethodForNullAnnotation(method, result);
597
	
592
	return result;
598
	return result;
593
}
599
}
594
600
Lines 1142-1147 Link Here
1142
	}
1148
	}
1143
	return this.storedAnnotations;
1149
	return this.storedAnnotations;
1144
}
1150
}
1151
void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) {
1152
	char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
1153
	char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
1154
	if (nullableAnnotationName == null || nonNullAnnotationName == null)
1155
		return; // not configured to use null annotations
1156
1157
	// return:
1158
	IBinaryAnnotation[] annotations = method.getAnnotations();
1159
	if (annotations != null) {
1160
		for (int i = 0; i < annotations.length; i++) {
1161
			char[] annotationTypeName = annotations[i].getTypeName();
1162
			if (annotationTypeName[0] != 'L')
1163
				continue;
1164
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1165
			if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1166
				methodBinding.tagBits |= TagBits.AnnotationNonNull;
1167
				break;
1168
			}
1169
			if (CharOperation.equals(typeName, nullableAnnotationName)) {
1170
				methodBinding.tagBits |= TagBits.AnnotationNullable;
1171
				break;
1172
			}
1173
		}
1174
	}
1175
1176
	// parameters:
1177
	TypeBinding[] parameters = methodBinding.parameters;
1178
	for (int j = 0; j < parameters.length; j++) {
1179
		IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j); 
1180
		if (paramAnnotations != null) {
1181
			for (int i = 0; i < paramAnnotations.length; i++) {
1182
				char[] annotationTypeName = paramAnnotations[i].getTypeName();
1183
				if (annotationTypeName[0] != 'L')
1184
					continue;
1185
				char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1186
				if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1187
					if (methodBinding.parameterNonNullness == null)
1188
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1189
					methodBinding.parameterNonNullness[j] = Boolean.TRUE;
1190
					break;
1191
				} else if (CharOperation.equals(typeName, nullableAnnotationName)) {
1192
					if (methodBinding.parameterNonNullness == null)
1193
						methodBinding.parameterNonNullness = new Boolean[parameters.length];
1194
					methodBinding.parameterNonNullness[j] = Boolean.FALSE;
1195
					break;
1196
				}
1197
			}
1198
		}
1199
	}
1200
}
1201
void scanTypeForNullAnnotation(IBinaryType binaryType) {
1202
	char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
1203
	if (nonNullByDefaultAnnotationName == null)
1204
		return; // not configured to use null annotations
1205
1206
	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
1207
	if (annotations != null) {
1208
		long annotationBit = 0L;
1209
		TypeBinding defaultNullness = null;
1210
		for (int i = 0; i < annotations.length; i++) {
1211
			char[] annotationTypeName = annotations[i].getTypeName();
1212
			if (annotationTypeName[0] != 'L')
1213
				continue;
1214
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1215
			if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
1216
				IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
1217
				if (elementValuePairs != null && elementValuePairs.length == 1) {
1218
					Object value = elementValuePairs[0].getValue();
1219
					if (value instanceof BooleanConstant
1220
						&& !((BooleanConstant)value).booleanValue()) 
1221
					{
1222
						// parameter is 'false': this means we cancel defaults from outer scopes:
1223
						annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
1224
						defaultNullness = ReferenceBinding.NULL_UNSPECIFIED;
1225
						break;
1226
					}
1227
				}
1228
				annotationBit = TagBits.AnnotationNonNullByDefault;
1229
				defaultNullness = this.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, false/*resolve*/);
1230
				break;
1231
			}
1232
		}
1233
		if (annotationBit != 0L) {
1234
			this.tagBits |= annotationBit;
1235
			if (CharOperation.equals(this.sourceName(), TypeConstants.PACKAGE_INFO_NAME))
1236
				this.getPackage().nullnessDefaultAnnotation = defaultNullness;
1237
		}
1238
	}
1239
}
1240
1145
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1241
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
1146
*
1242
*
1147
* NOTE: superclass of a binary type is resolved when needed
1243
* NOTE: superclass of a binary type is resolved when needed
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java (+91 lines)
Lines 76-81 Link Here
76
	public boolean isProcessingAnnotations = false;
76
	public boolean isProcessingAnnotations = false;
77
	public boolean mayTolerateMissingType = false;
77
	public boolean mayTolerateMissingType = false;
78
78
79
	boolean nullAnnotationsInitialized = false;
80
79
	final static int BUILD_FIELDS_AND_METHODS = 4;
81
	final static int BUILD_FIELDS_AND_METHODS = 4;
80
	final static int BUILD_TYPE_HIERARCHY = 1;
82
	final static int BUILD_TYPE_HIERARCHY = 1;
81
	final static int CHECK_AND_SET_IMPORTS = 2;
83
	final static int CHECK_AND_SET_IMPORTS = 2;
Lines 83-88 Link Here
83
85
84
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
86
	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
85
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
87
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
88
86
89
87
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
90
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
88
	this.typeRequestor = typeRequestor;
91
	this.typeRequestor = typeRequestor;
Lines 723-728 Link Here
723
* 3. Create the method bindings
726
* 3. Create the method bindings
724
*/
727
*/
725
public PackageBinding createPackage(char[][] compoundName) {
728
public PackageBinding createPackage(char[][] compoundName) {
729
	if (!this.nullAnnotationsInitialized)
730
		initNullAnnotationPackages();
726
	PackageBinding packageBinding = getPackage0(compoundName[0]);
731
	PackageBinding packageBinding = getPackage0(compoundName[0]);
727
	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
732
	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
728
		packageBinding = new PackageBinding(compoundName[0], this);
733
		packageBinding = new PackageBinding(compoundName[0], this);
Lines 1073-1078 Link Here
1073
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1078
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
1074
}
1079
}
1075
1080
1081
public char[][] getNullableAnnotationName() {
1082
	return this.globalOptions.nullableAnnotationName;
1083
}
1084
1085
public char[][] getNonNullAnnotationName() {
1086
	return this.globalOptions.nonNullAnnotationName;
1087
}
1088
1089
public char[][] getNonNullByDefaultAnnotationName() {
1090
	return this.globalOptions.nonNullByDefaultAnnotationName;
1091
}
1092
1093
/**
1094
 * Answer the type binding representing the null-annotation identified by the given tag bits.
1095
 * @param annotationTagBit tag bits potentially denoting a null-annotation
1096
 * @param resolve should the resulting type binding be resolved?
1097
 * @return the corresponding annotation type binding 
1098
 * 		or <code>null</code> if no annotation bits are contained in the given tag bits.
1099
 */
1100
public TypeBinding getNullAnnotationBinding(long annotationTagBit, boolean resolve) {
1101
	char[][] name = null;
1102
	if (annotationTagBit == TagBits.AnnotationNonNull)
1103
		name = getNonNullAnnotationName();
1104
	else if (annotationTagBit == TagBits.AnnotationNullable)
1105
		name = getNullableAnnotationName();
1106
	else
1107
		return null;
1108
	if (resolve)
1109
		return getType(name);
1110
	else
1111
		return getTypeFromCompoundName(name, false, false);
1112
}
1113
1114
/**
1115
 * Inspect the given tag bits and answer a corresponding null annotation type binding
1116
 * @param defaultTagBit tag bits representing the default applicable at the current code location
1117
 * @param resolve should the resulting type binding be resolved?
1118
 * @return the corresponding concrete annotation type binding (<code>@NonNull</code> or <code>@Nullable</code>) 
1119
 * 		or <code>null</code> if no bits of a default-annotation are contained in the given tag bits.
1120
 */
1121
public TypeBinding getNullAnnotationBindingFromDefault(long defaultTagBit, boolean resolve) {
1122
	if ((defaultTagBit & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
1123
		return ReferenceBinding.NULL_UNSPECIFIED;
1124
	if ((defaultTagBit & TagBits.AnnotationNonNullByDefault) != 0)
1125
		return getNullAnnotationBinding(TagBits.AnnotationNonNull, resolve);
1126
	return null;
1127
}
1128
1076
/* Answer the top level package named name if it exists in the cache.
1129
/* 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
1130
* Answer theNotFoundPackage if it could not be resolved the first time
1078
* it was looked up, otherwise answer null.
1131
* it was looked up, otherwise answer null.
Lines 1106-1111 Link Here
1106
* Answer null if the package cannot be found.
1159
* Answer null if the package cannot be found.
1107
*/
1160
*/
1108
PackageBinding getTopLevelPackage(char[] name) {
1161
PackageBinding getTopLevelPackage(char[] name) {
1162
	if (!this.nullAnnotationsInitialized)
1163
		initNullAnnotationPackages();
1109
	PackageBinding packageBinding = getPackage0(name);
1164
	PackageBinding packageBinding = getPackage0(name);
1110
	if (packageBinding != null) {
1165
	if (packageBinding != null) {
1111
		if (packageBinding == TheNotFoundPackage)
1166
		if (packageBinding == TheNotFoundPackage)
Lines 1387-1392 Link Here
1387
	}
1442
	}
1388
}
1443
}
1389
1444
1445
private void initNullAnnotationPackages() {
1446
	this.nullAnnotationsInitialized = true;
1447
	char[][] compoundName = getNullableAnnotationName();
1448
	if (compoundName != null)
1449
		initNullAnnotationPackage(compoundName, TypeIds.T_ConfiguredAnnotationNullable);
1450
	compoundName = getNonNullAnnotationName();
1451
	if (compoundName != null)
1452
		initNullAnnotationPackage(compoundName, TypeIds.T_ConfiguredAnnotationNonNull);
1453
	compoundName = getNonNullByDefaultAnnotationName();
1454
	if (compoundName != null)
1455
		initNullAnnotationPackage(compoundName, TypeIds.T_ConfiguredAnnotationNonNullByDefault);
1456
}
1457
1458
/** 
1459
 * Create or retrieve the package holding the specified type and store the type name.
1460
 */
1461
void initNullAnnotationPackage(char[][] typeName, int typeId) {
1462
	if (typeName.length < 2) {
1463
		this.problemReporter.nullAnnotationNameMustBeQualified(typeName);
1464
		return;
1465
	}
1466
	char[][] packageName = CharOperation.subarray(typeName, 0, typeName.length-1);
1467
	PackageBinding packageBinding = createPackage(packageName);
1468
	char[] simpleTypeName = typeName[typeName.length-1];
1469
	if (typeId == TypeIds.T_ConfiguredAnnotationNullable)
1470
		packageBinding.nullableName = simpleTypeName;
1471
	else if (typeId == TypeIds.T_ConfiguredAnnotationNonNull)
1472
		packageBinding.nonNullName = simpleTypeName;
1473
	else if (typeId == TypeIds.T_ConfiguredAnnotationNonNullByDefault)
1474
		packageBinding.nonNullByDefaultName = simpleTypeName;
1475
}
1476
1477
1390
boolean isMissingType(char[] typeName) {
1478
boolean isMissingType(char[] typeName) {
1391
	for (int i = this.missingTypes == null ? 0 : this.missingTypes.size(); --i >= 0;) {
1479
	for (int i = this.missingTypes == null ? 0 : this.missingTypes.size(); --i >= 0;) {
1392
		MissingTypeBinding missingType = (MissingTypeBinding) this.missingTypes.get(i);
1480
		MissingTypeBinding missingType = (MissingTypeBinding) this.missingTypes.get(i);
Lines 1454-1459 Link Here
1454
	this.unitBeingCompleted = null; // in case AbortException occurred
1542
	this.unitBeingCompleted = null; // in case AbortException occurred
1455
1543
1456
	this.classFilePool.reset();
1544
	this.classFilePool.reset();
1545
	
1546
	this.nullAnnotationsInitialized = false;
1547
1457
	// name environment has a longer life cycle, and must be reset in
1548
	// name environment has a longer life cycle, and must be reset in
1458
	// the code which created it.
1549
	// the code which created it.
1459
}
1550
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java (+38 lines)
Lines 34-39 Link Here
34
	char[] signature;
34
	char[] signature;
35
	public long tagBits;
35
	public long tagBits;
36
36
37
	/** Store nullness information from annotation (incl. applicable default). */
38
	public Boolean[] parameterNonNullness;  // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
39
37
protected MethodBinding() {
40
protected MethodBinding() {
38
	// for creating problem or synthetic method
41
	// for creating problem or synthetic method
39
}
42
}
Lines 439-444 Link Here
439
	return this.selector;
442
	return this.selector;
440
}
443
}
441
444
445
/** 
446
 * After method verifier has finished, fill in missing nullness values from the applicable default.
447
 * @param annotationBinding the null annotation specified to be the default at the current code location.
448
 */
449
protected void fillInDefaultNonNullness(TypeBinding annotationBinding) {
450
	if (this.parameterNonNullness == null)
451
		this.parameterNonNullness = new Boolean[this.parameters.length];
452
	AbstractMethodDeclaration sourceMethod = sourceMethod();
453
	for (int i = 0; i < this.parameterNonNullness.length; i++) {
454
		if (this.parameters[i].isBaseType())
455
			continue;
456
		boolean added = false;
457
		if (this.parameterNonNullness[i] == null) {
458
			added = true;
459
			this.parameterNonNullness[i] = Boolean.TRUE;
460
			if (sourceMethod != null)
461
				sourceMethod.addParameterNonNullAnnotation(i, (ReferenceBinding)annotationBinding);
462
		} else if (this.parameterNonNullness[i].booleanValue()) {
463
			sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
464
		}
465
		if (added)
466
			this.tagBits |= TagBits.HasParameterAnnotations;
467
	}
468
	if (   this.returnType != null
469
		&& !this.returnType.isBaseType()
470
		&& (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
471
	{
472
		this.tagBits |= TagBits.AnnotationNonNull;
473
		if (sourceMethod != null)
474
			sourceMethod.addNullnessAnnotation((ReferenceBinding)annotationBinding);
475
	} else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
476
		sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
477
	}
478
}
479
442
public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) {
480
public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) {
443
	MethodBinding inheritedOriginal = inheritedMethod.original();
481
	MethodBinding inheritedOriginal = inheritedMethod.original();
444
	TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass);
482
	TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (-1 / +97 lines)
Lines 164-169 Link Here
164
				|| this.type.superclass.erasure().findSuperTypeOriginatingFrom(originalInherited.declaringClass) == null)
164
				|| this.type.superclass.erasure().findSuperTypeOriginatingFrom(originalInherited.declaringClass) == null)
165
					this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original());
165
					this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original());
166
		}
166
		}
167
		if (!concreteMethod.isStatic() && !abstractMethod.isStatic())
168
			checkNullSpecInheritance(concreteMethod, abstractMethod);
167
	}
169
	}
168
}
170
}
169
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) {
171
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) {
Lines 358-363 Link Here
358
	}
360
	}
359
361
360
	return false;
362
	return false;
363
}
364
void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods) 
365
{
366
	super.checkAgainstInheritedMethods(currentMethod, methods, length, allInheritedMethods);
367
	for (int i = length; --i >= 0;)
368
		if (!currentMethod.isStatic() && !methods[i].isStatic())
369
			checkNullSpecInheritance(currentMethod, methods[i]);
370
}
371
372
void checkNullSpecInheritance(MethodBinding currentMethod, MethodBinding inheritedMethod) {
373
	long inheritedBits = inheritedMethod.tagBits;
374
	long currentBits = currentMethod.tagBits;
375
	AbstractMethodDeclaration srcMethod = null;
376
	if (this.type.equals(currentMethod.declaringClass)) // is currentMethod from the current type?
377
		srcMethod = currentMethod.sourceMethod();
378
379
	// return type:
380
	if ((inheritedBits & TagBits.AnnotationNonNull) != 0) {
381
		long currentNullBits = currentBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable);
382
		if (currentNullBits != TagBits.AnnotationNonNull) {
383
			if (srcMethod != null) {
384
				this.type.scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod,
385
															this.environment.getNonNullAnnotationName());
386
			} else {
387
				this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
388
				return;
389
			}
390
		}
391
	}
392
393
	// parameters:
394
	Argument[] currentArguments = srcMethod == null ? null : srcMethod.arguments;
395
	if (inheritedMethod.parameterNonNullness != null) {
396
		// inherited method has null-annotations, check compatibility:
397
398
		for (int i = 0; i < inheritedMethod.parameterNonNullness.length; i++) {
399
			Argument currentArgument = currentArguments == null ? null : currentArguments[i];
400
			
401
			Boolean inheritedNonNullNess = inheritedMethod.parameterNonNullness[i];
402
			Boolean currentNonNullNess = (currentMethod.parameterNonNullness == null)
403
										? null : currentMethod.parameterNonNullness[i];
404
			if (inheritedNonNullNess != null) {				// super has a null annotation
405
				if (currentNonNullNess == null) {			// current parameter lacks null annotation
406
					boolean needNonNull = false;
407
					char[][] annotationName;
408
					if (inheritedNonNullNess == Boolean.TRUE) {
409
						needNonNull = true;
410
						annotationName = this.environment.getNonNullAnnotationName();
411
					} else {
412
						annotationName = this.environment.getNullableAnnotationName();
413
					}
414
					if (currentArgument != null) {
415
						this.type.scope.problemReporter().parameterLackingNonNullAnnotation(
416
								currentArgument,
417
								inheritedMethod.declaringClass,
418
								needNonNull,
419
								annotationName);
420
						continue;
421
					} else {
422
						this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
423
						break;
424
					}
425
				}						
426
			}
427
			if (inheritedNonNullNess != Boolean.TRUE) {		// super parameter is not restricted to @NonNull
428
				if (currentNonNullNess == Boolean.TRUE) { 	// current parameter is restricted to @NonNull
429
					if (currentArgument != null)
430
						this.type.scope.problemReporter().illegalRedefinitionToNonNullParameter(
431
														currentArgument,
432
														inheritedMethod.declaringClass,
433
														inheritedNonNullNess == null
434
														? null
435
														: this.environment.getNullableAnnotationName());
436
					else
437
						this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
438
				} 
439
			}
440
		}
441
	} else if (currentMethod.parameterNonNullness != null) {
442
		// super method has no annotations but current has
443
		for (int i = 0; i < currentMethod.parameterNonNullness.length; i++) {
444
			if (currentMethod.parameterNonNullness[i] == Boolean.TRUE) { // tightening from unconstrained to @NonNull
445
				if (currentArguments != null) {
446
					this.type.scope.problemReporter().illegalRedefinitionToNonNullParameter(
447
																	currentArguments[i],
448
																	inheritedMethod.declaringClass,
449
																	null);
450
				} else {
451
					this.type.scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod);
452
					break;
453
				}
454
			}
455
		}
456
	}
361
}
457
}
362
458
363
void reportRawReferences() {
459
void reportRawReferences() {
Lines 932-938 Link Here
932
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
1028
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
933
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
1029
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
934
1030
935
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
1031
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
936
	if (currentMethod.returnType == inheritedMethod.returnType.erasure()) {
1032
	if (currentMethod.returnType == inheritedMethod.returnType.erasure()) {
937
		TypeBinding[] currentParams = currentMethod.parameters;
1033
		TypeBinding[] currentParams = currentMethod.parameters;
938
		TypeBinding[] inheritedParams = inheritedMethod.parameters;
1034
		TypeBinding[] inheritedParams = inheritedMethod.parameters;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java (-1 / +29 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 22-27 Link Here
22
	public LookupEnvironment environment;
22
	public LookupEnvironment environment;
23
	HashtableOfType knownTypes;
23
	HashtableOfType knownTypes;
24
	HashtableOfPackage knownPackages;
24
	HashtableOfPackage knownPackages;
25
26
	protected char[] nullableName = null;
27
	protected char[] nonNullName = null;
28
	protected char[] nonNullByDefaultName = null;
29
	protected TypeBinding nullnessDefaultAnnotation;
30
25
protected PackageBinding() {
31
protected PackageBinding() {
26
	// for creating problem package
32
	// for creating problem package
27
}
33
}
Lines 58-63 Link Here
58
	if (this.knownTypes == null)
64
	if (this.knownTypes == null)
59
		this.knownTypes = new HashtableOfType(25);
65
		this.knownTypes = new HashtableOfType(25);
60
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
66
	this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
67
	if (this.nullableName != null || this.nonNullName != null || this.nonNullByDefaultName != null)
68
		setupNullAnnotationType(element);
61
}
69
}
62
70
63
void clearMissingTagBit() {
71
void clearMissingTagBit() {
Lines 230-235 Link Here
230
	return ProblemReasons.NoError;
238
	return ProblemReasons.NoError;
231
}
239
}
232
240
241
void setupNullAnnotationType(ReferenceBinding type) {
242
	int id = 0;
243
	if (CharOperation.equals(this.nullableName, type.sourceName))
244
		id = TypeIds.T_ConfiguredAnnotationNullable;
245
	else if (CharOperation.equals(this.nonNullName, type.sourceName))
246
		id = TypeIds.T_ConfiguredAnnotationNonNull;
247
	else if (CharOperation.equals(this.nonNullByDefaultName, type.sourceName))
248
		id = TypeIds.T_ConfiguredAnnotationNonNullByDefault;
249
	else 
250
		return;
251
	
252
	type.id = id;	// ensure annotations of this type are detected as standard annotations.
253
}
254
255
public TypeBinding getNullnessDefaultAnnotation() {
256
	if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
257
		return this.nullnessDefaultAnnotation = BinaryTypeBinding.resolveType(this.nullnessDefaultAnnotation, this.environment, false);
258
	return this.nullnessDefaultAnnotation;
259
}
260
233
public char[] readableName() /*java.lang*/ {
261
public char[] readableName() /*java.lang*/ {
234
	return CharOperation.concatWith(this.compoundName, '.');
262
	return CharOperation.concatWith(this.compoundName, '.');
235
}
263
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+8 lines)
Lines 48-53 Link Here
48
		public boolean hasTypeBit(int bit) { return false; }
48
		public boolean hasTypeBit(int bit) { return false; }
49
	};
49
	};
50
50
51
	/**
52
	 * This faked annotation type binding marks types with unspecified nullness.
53
	 * For use in {@link PackageBinding#nullnessDefaultAnnotation} and {@link SourceTypeBinding#nullnessDefaultAnnotation} 
54
	 */
55
	final static ReferenceBinding NULL_UNSPECIFIED = new ReferenceBinding() { /* faked type binding */
56
		public boolean hasTypeBit(int bit) { return false; }
57
	};
58
51
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
59
	private static final Comparator FIELD_COMPARATOR = new Comparator() {
52
		public int compare(Object o1, Object o2) {
60
		public int compare(Object o1, Object o2) {
53
			char[] n1 = ((FieldBinding) o1).name;
61
			char[] n1 = ((FieldBinding) o1).name;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (+97 lines)
Lines 54-59 Link Here
54
	char[] genericReferenceTypeSignature;
54
	char[] genericReferenceTypeSignature;
55
55
56
	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
56
	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
57
	
58
	private TypeBinding nullnessDefaultAnnotation;
59
	private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
57
60
58
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
61
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
59
	this.compoundName = compoundName;
62
	this.compoundName = compoundName;
Lines 781-786 Link Here
781
		}
784
		}
782
		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
785
		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
783
			this.modifiers |= ClassFileConstants.AccDeprecated;
786
			this.modifiers |= ClassFileConstants.AccDeprecated;
787
		evaluateNullAnnotations(this.tagBits);
784
	}
788
	}
785
	return this.tagBits;
789
	return this.tagBits;
786
}
790
}
Lines 1088-1093 Link Here
1088
			this.modifiers |= ClassFileConstants.AccDeprecated;
1092
			this.modifiers |= ClassFileConstants.AccDeprecated;
1089
		}
1093
		}
1090
	}
1094
	}
1095
	if (CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME))
1096
		getAnnotationTagBits(); // initialize
1091
}
1097
}
1092
1098
1093
// ensure the receiver knows its hierarchy & fields/methods so static imports can be resolved correctly
1099
// 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;
1596
				typeParameters[i].binding = null;
1591
		return null;
1597
		return null;
1592
	}
1598
	}
1599
	callBindArguments(method);
1593
	if (foundReturnTypeProblem)
1600
	if (foundReturnTypeProblem)
1594
		return method; // but its still unresolved with a null return type & is still connected to its method declaration
1601
		return method; // but its still unresolved with a null return type & is still connected to its method declaration
1595
1602
1596
	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1603
	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1597
	return method;
1604
	return method;
1598
}
1605
}
1606
private void callBindArguments(MethodBinding method) {
1607
	switch (this.nullnessDefaultInitialized) {
1608
	case 0:
1609
		getAnnotationTagBits(); // initialize
1610
		//$FALL-THROUGH$
1611
	case 1:
1612
		getPackage().isViewedAsDeprecated(); // initialize annotations
1613
		this.nullnessDefaultInitialized = 2;
1614
	}
1615
	AbstractMethodDeclaration methodDecl = method.sourceMethod();
1616
	if (methodDecl != null) {
1617
		if (method.parameters != Binding.NO_PARAMETERS)
1618
			methodDecl.bindArguments();
1619
		TypeBinding annotationBinding = findDefaultNullness(method, methodDecl.scope.environment());
1620
		if (annotationBinding != null && annotationBinding.id == TypeIds.T_ConfiguredAnnotationNonNull)
1621
			method.fillInDefaultNonNullness(annotationBinding);
1622
	}
1623
}
1624
private void evaluateNullAnnotations(long annotationTagBits) {
1625
	if (this.nullnessDefaultInitialized > 0)
1626
		return;
1627
	this.nullnessDefaultInitialized = 1;
1628
	// transfer nullness info from tagBits to this.nullnessDefaultAnnotation 
1629
	TypeBinding defaultAnnotation = getPackage().environment
1630
						.getNullAnnotationBindingFromDefault(annotationTagBits, false/*resolve*/);
1631
	if (defaultAnnotation != null) {
1632
		if (CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME)) {
1633
			getPackage().nullnessDefaultAnnotation = defaultAnnotation;
1634
		} else {
1635
			this.nullnessDefaultAnnotation = defaultAnnotation;
1636
		}
1637
	}
1638
}
1639
private TypeBinding getNullnessDefaultAnnotation() {
1640
	if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
1641
		return this.nullnessDefaultAnnotation =
1642
				BinaryTypeBinding.resolveType(this.nullnessDefaultAnnotation, getPackage().environment, false);
1643
	return this.nullnessDefaultAnnotation;
1644
}
1645
/**
1646
 * Answer the nullness default applicable at the given method binding.
1647
 * Possible values:<ul>
1648
 * <li>the type binding for @NonNulByDefault</li>
1649
 * <li>the synthetic type {@link ReferenceBinding#NULL_UNSPECIFIED} if a default from outer scope has been canceled</li>
1650
 * <li>null if no default has been defined</li>
1651
 * </ul>
1652
 */
1653
private TypeBinding findDefaultNullness(MethodBinding methodBinding, LookupEnvironment environment) {
1654
	// find the applicable default inside->out:
1655
	
1656
	// method
1657
	TypeBinding annotationBinding = environment.getNullAnnotationBindingFromDefault(methodBinding.tagBits, true/*resolve*/);
1658
	if (annotationBinding != null)
1659
		return annotationBinding;
1660
	
1661
	// type
1662
	ReferenceBinding type = methodBinding.declaringClass;
1663
	ReferenceBinding currentType = type;
1664
	while (currentType instanceof SourceTypeBinding) {
1665
		annotationBinding = ((SourceTypeBinding) currentType).getNullnessDefaultAnnotation();
1666
		if (annotationBinding != null)
1667
			return annotationBinding;
1668
		currentType = currentType.enclosingType();
1669
	}
1670
	
1671
	// package
1672
	annotationBinding = type.getPackage().getNullnessDefaultAnnotation();
1673
	if (annotationBinding != null)
1674
		return annotationBinding;
1675
	
1676
	// global
1677
	long defaultNullness = environment.globalOptions.defaultNonNullness;
1678
	if (defaultNullness != 0) {
1679
		annotationBinding = environment.getNullAnnotationBinding(defaultNullness, true/*resolve*/);
1680
		if (annotationBinding != null)
1681
			return annotationBinding;
1682
		
1683
		// on this branch default was not defined using an annotation, thus annotation type can still be missing
1684
		if (defaultNullness == TagBits.AnnotationNonNull)
1685
			this.scope.problemReporter().missingNullAnnotationType(environment.getNonNullAnnotationName());
1686
		else if (defaultNullness == TagBits.AnnotationNullable)
1687
			this.scope.problemReporter().missingNullAnnotationType(environment.getNullableAnnotationName());
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 / +15 lines)
Lines 132-137 Link Here
132
	long AnnotationPreDestroy = ASTNode.Bit54L;
132
	long AnnotationPreDestroy = ASTNode.Bit54L;
133
	/** @since 3.8 */
133
	/** @since 3.8 */
134
	long AnnotationPostConstruct = ASTNode.Bit55L;
134
	long AnnotationPostConstruct = ASTNode.Bit55L;
135
	/** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */
136
	long AnnotationNullable = ASTNode.Bit56L;
137
	/** @since 3.8 null annotation for MethodBinding or LocalVariableBinding (argument): */
138
	long AnnotationNonNull = ASTNode.Bit57L;
139
	/** @since 3.8 null-default annotation for PackageBinding or TypeBinding or MethodBinding: */
140
	long AnnotationNonNullByDefault = ASTNode.Bit58L;
141
	/** @since 3.8 canceling null-default annotation for PackageBinding or TypeBinding or MethodBinding: */
142
	long AnnotationNullUnspecifiedByDefault = ASTNode.Bit59L;
135
143
136
	long AllStandardAnnotationsMask =
144
	long AllStandardAnnotationsMask =
137
				  AnnotationTargetMASK
145
				  AnnotationTargetMASK
Lines 144-153 Link Here
144
				| AnnotationSafeVarargs
152
				| AnnotationSafeVarargs
145
				| AnnotationPolymorphicSignature
153
				| AnnotationPolymorphicSignature
146
				| AnnotationPostConstruct
154
				| AnnotationPostConstruct
147
				| AnnotationPreDestroy;
155
				| AnnotationPreDestroy
156
				| AnnotationNullable
157
				| AnnotationNonNull
158
				| AnnotationNonNullByDefault
159
				| AnnotationNullUnspecifiedByDefault;
148
160
149
	long DefaultValueResolved = ASTNode.Bit56L;
161
	long DefaultValueResolved = ASTNode.Bit60L;
150
162
151
	// set when type contains non-private constructor(s)
163
	// set when type contains non-private constructor(s)
152
	long HasNonPrivateConstructor = ASTNode.Bit57L;
164
	long HasNonPrivateConstructor = ASTNode.Bit61L;
153
}
165
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (+5 lines)
Lines 104-109 Link Here
104
	final int T_JavaxAnnotationPostConstruct = 63;
104
	final int T_JavaxAnnotationPostConstruct = 63;
105
105
106
	final int T_JavaxAnnotationPreDestroy = 64;
106
	final int T_JavaxAnnotationPreDestroy = 64;
107
	
108
	// new in 3.8 for null annotations:
109
	final int T_ConfiguredAnnotationNullable = 65;
110
	final int T_ConfiguredAnnotationNonNull = 66;
111
	final int T_ConfiguredAnnotationNonNullByDefault = 67;
107
112
108
	final int NoId = Integer.MAX_VALUE;
113
	final int NoId = Integer.MAX_VALUE;
109
114
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (+196 lines)
Lines 84-89 Link Here
84
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
84
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
85
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
85
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
86
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
86
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
87
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
87
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
88
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
88
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
89
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
89
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
90
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
Lines 287-292 Link Here
287
			return CompilerOptions.NullReference;
288
			return CompilerOptions.NullReference;
288
289
289
		case IProblem.PotentialNullLocalVariableReference:
290
		case IProblem.PotentialNullLocalVariableReference:
291
		case IProblem.PotentialNullMessageSendReference:
290
			return CompilerOptions.PotentialNullReference;
292
			return CompilerOptions.PotentialNullReference;
291
293
292
		case IProblem.RedundantLocalVariableNullAssignment:
294
		case IProblem.RedundantLocalVariableNullAssignment:
Lines 295-301 Link Here
295
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
297
		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
296
		case IProblem.NullLocalVariableComparisonYieldsFalse:
298
		case IProblem.NullLocalVariableComparisonYieldsFalse:
297
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
299
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
300
		case IProblem.RedundantNullCheckOnNonNullMessageSend:
298
			return CompilerOptions.RedundantNullCheck;
301
			return CompilerOptions.RedundantNullCheck;
302
303
		case IProblem.RequiredNonNullButProvidedNull:
304
		case IProblem.IllegalReturnNullityRedefinition:
305
		case IProblem.IllegalRedefinitionToNonNullParameter:
306
		case IProblem.IllegalDefinitionToNonNullParameter:
307
		case IProblem.ParameterLackingNonNullAnnotation:
308
		case IProblem.ParameterLackingNullableAnnotation:
309
		case IProblem.CannotImplementIncompatibleNullness:
310
			return CompilerOptions.NullSpecViolation;
311
		
312
		case IProblem.RequiredNonNullButProvidedPotentialNull:
313
			return CompilerOptions.PotentialNullSpecViolation;
314
		case IProblem.RequiredNonNullButProvidedUnknown:
315
			return CompilerOptions.NullSpecInsufficientInfo;
316
		case IProblem.RedundantNullAnnotation:
317
			return CompilerOptions.RedundantNullAnnotation;
299
318
300
		case IProblem.BoxingConversion :
319
		case IProblem.BoxingConversion :
301
		case IProblem.UnboxingConversion :
320
		case IProblem.UnboxingConversion :
Lines 542-547 Link Here
542
			case CompilerOptions.DiscouragedReference :
561
			case CompilerOptions.DiscouragedReference :
543
				return CategorizedProblem.CAT_RESTRICTION;
562
				return CategorizedProblem.CAT_RESTRICTION;
544
			
563
			
564
			case CompilerOptions.NullSpecViolation :
565
			case CompilerOptions.PotentialNullSpecViolation :
566
			case CompilerOptions.NullSpecInsufficientInfo :
567
				return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
568
			case CompilerOptions.RedundantNullAnnotation :
569
				return CategorizedProblem.CAT_UNNECESSARY_CODE;
570
545
			default:
571
			default:
546
				break categorizeOnIrritant;
572
				break categorizeOnIrritant;
547
		}
573
		}
Lines 550-555 Link Here
550
	switch (problemID) {
576
	switch (problemID) {
551
		case IProblem.IsClassPathCorrect :
577
		case IProblem.IsClassPathCorrect :
552
		case IProblem.CorruptedSignature :
578
		case IProblem.CorruptedSignature :
579
		case IProblem.MissingNullAnnotationType :
580
		case IProblem.NullAnnotationNameMustBeQualified :
553
			return CategorizedProblem.CAT_BUILDPATH;
581
			return CategorizedProblem.CAT_BUILDPATH;
554
582
555
		default :
583
		default :
Lines 7999-8002 Link Here
7999
		trackVar.sourceStart,
8027
		trackVar.sourceStart,
8000
		trackVar.sourceEnd);	
8028
		trackVar.sourceEnd);	
8001
}
8029
}
8030
8031
public void nullityMismatch(Expression expression, TypeBinding requiredType, int nullStatus, char[][] annotationName) {
8032
	int problemId = IProblem.RequiredNonNullButProvidedUnknown;
8033
	if ((nullStatus & FlowInfo.NULL) != 0)
8034
		problemId = IProblem.RequiredNonNullButProvidedNull;
8035
	if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
8036
		problemId = IProblem.RequiredNonNullButProvidedPotentialNull;
8037
	String[] arguments = new String[] { 
8038
			String.valueOf(CharOperation.concatWith(annotationName, '.')),
8039
			String.valueOf(requiredType.readableName())
8040
	};
8041
	String[] argumentsShort = new String[] { 
8042
			String.valueOf(annotationName[annotationName.length-1]),
8043
			String.valueOf(requiredType.shortReadableName())
8044
	};
8045
	this.handle(
8046
		problemId,
8047
		arguments,
8048
		argumentsShort,
8049
		expression.sourceStart,
8050
		expression.sourceEnd);
8051
}
8052
public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
8053
	int sourceStart = argument.type.sourceStart;
8054
	if (argument.annotations != null) {
8055
		for (int i=0; i<argument.annotations.length; i++) {
8056
			Annotation annotation = argument.annotations[i];
8057
			if (   annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable
8058
				|| annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull) 
8059
			{
8060
				sourceStart = annotation.sourceStart;
8061
				break;
8062
			}
8063
		}
8064
	}
8065
	if (inheritedAnnotationName == null) {
8066
		this.handle(
8067
			IProblem.IllegalDefinitionToNonNullParameter, 
8068
			new String[] { new String(argument.name), new String(declaringClass.readableName()) },
8069
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()) },
8070
			sourceStart,
8071
			argument.type.sourceEnd);
8072
		
8073
	} else {
8074
		this.handle(
8075
			IProblem.IllegalRedefinitionToNonNullParameter, 
8076
			new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8077
			new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8078
			sourceStart,
8079
			argument.type.sourceEnd);
8080
	}
8081
}
8082
public void parameterLackingNonNullAnnotation(Argument argument, ReferenceBinding declaringClass, boolean needNonNull, char[][] inheritedAnnotationName) {
8083
	this.handle(
8084
		needNonNull ? IProblem.ParameterLackingNonNullAnnotation : IProblem.ParameterLackingNullableAnnotation, 
8085
		new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
8086
		new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
8087
		argument.type.sourceStart,
8088
		argument.type.sourceEnd);
8089
}
8090
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl,
8091
									  MethodBinding inheritedMethod, char[][] nonNullAnnotationName) 
8092
{
8093
	MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl;
8094
	StringBuffer methodSignature = new StringBuffer();
8095
	methodSignature
8096
		.append(inheritedMethod.declaringClass.readableName())
8097
		.append('.')
8098
		.append(inheritedMethod.readableName());
8099
8100
	StringBuffer shortSignature = new StringBuffer();
8101
	shortSignature
8102
		.append(inheritedMethod.declaringClass.shortReadableName())
8103
		.append('.')
8104
		.append(inheritedMethod.shortReadableName());
8105
	int sourceStart = methodDecl.returnType.sourceStart;
8106
	Annotation[] annotations = methodDecl.annotations;
8107
	if (annotations != null) {
8108
		for (int i=0; i<annotations.length; i++) {
8109
			if (annotations[i].resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable) {
8110
				sourceStart = annotations[i].sourceStart;
8111
				break;
8112
			}
8113
		}
8114
	}
8115
	this.handle(
8116
		IProblem.IllegalReturnNullityRedefinition, 
8117
		new String[] { methodSignature.toString(), CharOperation.toString(nonNullAnnotationName)},
8118
		new String[] { shortSignature.toString(), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])},
8119
		sourceStart, 
8120
		methodDecl.returnType.sourceEnd);
8121
}
8122
public void messageSendPotentialNullReference(MethodBinding method, ASTNode location) {
8123
	String[] arguments = new String[] {new String(method.readableName())};
8124
	this.handle(
8125
		IProblem.PotentialNullMessageSendReference,
8126
		arguments,
8127
		arguments,
8128
		location.sourceStart,
8129
		location.sourceEnd);
8130
}
8131
public void messageSendRedundantCheckOnNonNull(MethodBinding method, ASTNode location) {
8132
	String[] arguments = new String[] {new String(method.readableName())  };
8133
	this.handle(
8134
		IProblem.RedundantNullCheckOnNonNullMessageSend,
8135
		arguments,
8136
		arguments,
8137
		location.sourceStart,
8138
		location.sourceEnd);
8139
}
8140
8141
public void missingNullAnnotationType(char[][] nullAnnotationName) {
8142
	String[] args = { new String(CharOperation.concatWith(nullAnnotationName, '.')) };
8143
	this.handle(IProblem.MissingNullAnnotationType, args, args, 0, 0);	
8144
}
8145
8146
public void cannotImplementIncompatibleNullness(MethodBinding currentMethod, MethodBinding inheritedMethod) {
8147
	int sourceStart = 0, sourceEnd = 0;
8148
	if (this.referenceContext instanceof TypeDeclaration) {
8149
		sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart;
8150
		sourceEnd =   ((TypeDeclaration) this.referenceContext).sourceEnd;
8151
	}
8152
	String[] problemArguments = {
8153
			new String(currentMethod.readableName()),
8154
			new String(currentMethod.declaringClass.readableName()),
8155
			new String(inheritedMethod.declaringClass.readableName())
8156
		};
8157
	String[] messageArguments = {
8158
			new String(currentMethod.shortReadableName()),
8159
			new String(currentMethod.declaringClass.shortReadableName()),
8160
			new String(inheritedMethod.declaringClass.shortReadableName())
8161
		};
8162
	this.handle(
8163
			IProblem.CannotImplementIncompatibleNullness,
8164
			problemArguments,
8165
			messageArguments,
8166
			sourceStart,
8167
			sourceEnd);
8168
}
8169
8170
public void nullAnnotationNameMustBeQualified(char[][] typeName) {
8171
	String[] name = {new String(typeName[0])};
8172
	this.handle(IProblem.NullAnnotationNameMustBeQualified, name, name, 0, 0);
8173
}
8174
8175
public void nullAnnotationIsRedundant(AbstractMethodDeclaration sourceMethod, int i) {
8176
	int sourceStart, sourceEnd;
8177
	if (i == -1) {
8178
		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration decl = sourceMethod;
8179
		org.eclipse.jdt.internal.compiler.ast.MethodDeclaration methodDecl = (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) decl;
8180
		sourceStart = methodDecl.returnType.sourceStart;
8181
		if (methodDecl.annotations != null) {
8182
			// should have a @NonNull annotation, search for it:
8183
			for (int j=0; j<methodDecl.annotations.length; j++) {
8184
				if (methodDecl.annotations[j].resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull) {
8185
					sourceStart = methodDecl.annotations[j].sourceStart;
8186
					break;
8187
				}
8188
			}
8189
		}
8190
		sourceEnd = methodDecl.returnType.sourceEnd;
8191
	} else {
8192
		Argument arg = sourceMethod.arguments[i];
8193
		sourceStart = arg.declarationSourceStart;
8194
		sourceEnd = arg.sourceEnd;
8195
	}
8196
	this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
8197
}
8002
}
8198
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (+16 lines)
Lines 653-658 Link Here
653
889 = Resource ''{0}'' should be managed by try-with-resource
653
889 = Resource ''{0}'' should be managed by try-with-resource
654
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
654
890 = Cannot switch on an enum value for source level below 1.5. Only convertible int values are permitted
655
655
656
### NULL ANNOTATIONS
657
910 = Type mismatch: required '@{0} {1}' but the provided value is null
658
911 = Type mismatch: required '@{0} {1}' but the provided value can be null
659
912 = Potential type mismatch: required '@{0} {1}' but nullness of the provided value is unknown
660
913 = Buildpath problem: the type {0} which is configured as a null annotation type cannot be resolved
661
914 = Cannot use the unqualified name ''{0}'' as an annotation name for null specification
662
915 = The return type is incompatible with the @{1} return from {0}
663
916 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
664
917 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
665
918 = Missing null annotation: inherited method from {1} declares this parameter as @{2}
666
919 = Missing null annotation: inherited method from {1} declares this parameter as @{2}
667
920 = Potential null pointer access: The method {0} may return null
668
921 = Redundant null check: The method {0} cannot return null
669
922 = The method {0} from class {1} cannot implement the corresponding method from type {2} due to incompatible nullness constraints
670
923 = The nullness annotation is redundant with a default that applies to this location
671
656
### ELABORATIONS
672
### ELABORATIONS
657
## Access restrictions
673
## Access restrictions
658
78592 = The type {1} is not accessible due to restriction on classpath entry {0}
674
78592 = The type {1} is not accessible due to restriction on classpath entry {0}

Return to bug 186342