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

Collapse All | Expand All

(-)batch/org/eclipse/jdt/internal/compiler/batch/Main.java (+22 lines)
Lines 12-17 Link Here
12
 *     Benjamin Muskalla - Contribution for bug 239066
12
 *     Benjamin Muskalla - Contribution for bug 239066
13
 *     Stephan Herrmann  - Contribution for bug 236385
13
 *     Stephan Herrmann  - Contribution for bug 236385
14
 *     Stephan Herrmann  - Contribution for bug 295551
14
 *     Stephan Herrmann  - Contribution for bug 295551
15
 *     Stephan Herrmann  - Contribution for bug 186342
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.batch;
17
package org.eclipse.jdt.internal.compiler.batch;
17
18
Lines 2388-2393 Link Here
2388
					mode = INSIDE_WARNINGS_PROPERTIES;
2389
					mode = INSIDE_WARNINGS_PROPERTIES;
2389
					continue;
2390
					continue;
2390
				}
2391
				}
2392
				if (currentArg.startsWith("-nullAnnotations:")) { //$NON-NLS-1$
2393
					StringTokenizer tokenizer =
2394
						new StringTokenizer(currentArg.substring("-nullAnnotations:".length()), ","); //$NON-NLS-1$ //$NON-NLS-2$
2395
					while (tokenizer.hasMoreTokens()) {
2396
						String token = tokenizer.nextToken();
2397
						if (token.startsWith("nullable=")) { //$NON-NLS-1$
2398
							this.options.put(CompilerOptions.OPTION_NullableAnnotationName, token.substring("nullable=".length())); //$NON-NLS-1$
2399
						} else if (token.startsWith("nonnull=")) { //$NON-NLS-1$
2400
							this.options.put(CompilerOptions.OPTION_NonNullAnnotationName, token.substring("nonnull=".length())); //$NON-NLS-1$
2401
						} else if (token.equals("emulate")) { //$NON-NLS-1$
2402
							this.options.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.ENABLED);
2403
						} else if (token.equals("import")) { //$NON-NLS-1$
2404
							this.options.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED);
2405
						} else {
2406
							throw new IllegalArgumentException(
2407
								this.bind("configure.unrecognized.nullannotation.option", token)); //$NON-NLS-1$
2408
						}
2409
					}
2410
					mode = DEFAULT;
2411
					continue;
2412
				}
2391
				break;
2413
				break;
2392
			case INSIDE_TARGET :
2414
			case INSIDE_TARGET :
2393
				if (this.didSpecifyTarget) {
2415
				if (this.didSpecifyTarget) {
(-)batch/org/eclipse/jdt/internal/compiler/batch/messages.properties (+18 lines)
Lines 8-13 Link Here
8
# Contributors:
8
# Contributors:
9
#     IBM Corporation - initial API and implementation
9
#     IBM Corporation - initial API and implementation
10
#		Benjamin Muskalla - Contribution for bug 239066
10
#		Benjamin Muskalla - Contribution for bug 239066
11
#       Stephan Herrmann  - Contribution for bug 186342
11
###############################################################################
12
###############################################################################
12
### JavaBatchCompiler messages.
13
### JavaBatchCompiler messages.
13
14
Lines 71-76 Link Here
71
72
72
## configure.directoryNotExist = directory does not exist: {0}
73
## configure.directoryNotExist = directory does not exist: {0}
73
configure.unrecognizedOption = Unrecognized option : {0}
74
configure.unrecognizedOption = Unrecognized option : {0}
75
configure.unrecognized.nullannotation.option = Unrecognized sub-option of -nullAnnotations: {0},\nlegal values are 'nullable=..', 'nonnull=..', 'emulate' and 'import'
74
configure.noClasspath = no classpath defined, using default directory instead
76
configure.noClasspath = no classpath defined, using default directory instead
75
configure.incorrectClasspath = incorrect classpath: {0}
77
configure.incorrectClasspath = incorrect classpath: {0}
76
configure.invalidexpansionargumentname = expansion argument file {0} does not exist or cannot be read
78
configure.invalidexpansionargumentname = expansion argument file {0} does not exist or cannot be read
Lines 222-227 Link Here
222
\    -classNames <className1[,className2,...]>\n\
224
\    -classNames <className1[,className2,...]>\n\
223
\                         qualified names of binary classes to process\n\
225
\                         qualified names of binary classes to process\n\
224
\ \n\
226
\ \n\
227
\ Null annotation options:\n\
228
\    -nullAnnotations:<suboptions>\n\
229
\                      enable use of annotations for specifying null contracts;\n\
230
\                      <suboptions> is a non-empty, comma-separated list of:\n\
231
\        nullable=<typename>\n\
232
\                      specifies the fully qualified name of an annotation type\n\
233
\                      to be used for marking types whose values include null\n\
234
\        nonnull=<typename>\n\
235
\                      specifies the fully qualified name of an annotation type\n\
236
\                      to be used for marking types whose values cannot be null\n\
237
\        emulate       tells the compiler to emulate the above annotation types\n\
238
\                      although they do not exist on the classpath\n\
239
\        import        tells the compiler to import the above annotation types\n\
240
\                      without specific mention in the sources such that their\n\
241
\                      simple names can be used without explicit imports\n\
242
\ \n\
225
\ Advanced options:\n\
243
\ Advanced options:\n\
226
\    @<file>            read command line arguments from file\n\
244
\    @<file>            read command line arguments from file\n\
227
\    -maxProblems <n>   max number of problems per compilation unit (100 by\n\
245
\    -maxProblems <n>   max number of problems per compilation unit (100 by\n\
(-)compiler/org/eclipse/jdt/core/compiler/IProblem.java (-1 / +32 lines)
Lines 116-122 Link Here
116
 *		Benjamin Muskalla - added the following constants
116
 *		Benjamin Muskalla - added the following constants
117
 *									MissingSynchronizedModifierInInheritedMethod
117
 *									MissingSynchronizedModifierInInheritedMethod
118
 *		Stephan Herrmann  - added the following constants
118
 *		Stephan Herrmann  - added the following constants
119
 *									UnusedObjectAllocation									
119
 *									UnusedObjectAllocation
120
 *									DefiniteNullFromNonNullMethod
121
 *									PotentialNullFromNonNullMethod
122
 *									NonNullReturnInsufficientInfo
123
 *									DefiniteNullToNonnullParameter
124
 *									PotentialNullToNonnullParameter
125
 *									NonNullParameterInsufficientInfo
126
 *									ConflictingTypeEmulation
127
 *									IllegalRedefinitionToNullableReturn
128
 *									IllegalRedefinitionToNonNullParameter
120
 *******************************************************************************/
129
 *******************************************************************************/
121
package org.eclipse.jdt.core.compiler;
130
package org.eclipse.jdt.core.compiler;
122
131
Lines 1340-1345 Link Here
1340
	int JavadocTypeArgumentsForRawGenericConstructor = Javadoc + Internal + 859;
1349
	int JavadocTypeArgumentsForRawGenericConstructor = Javadoc + Internal + 859;
1341
1350
1342
	/**
1351
	/**
1352
	 * Null Annotations
1353
	 */
1354
	/** @since 3.7 */
1355
	int DefiniteNullFromNonNullMethod = MethodRelated + 880;
1356
	/** @since 3.7 */
1357
	int PotentialNullFromNonNullMethod = MethodRelated + 881;
1358
	/** @since 3.7 */
1359
	int NonNullReturnInsufficientInfo = MethodRelated + 882;
1360
	/** @since 3.7 */
1361
	int DefiniteNullToNonnullParameter = MethodRelated + 883;
1362
	/** @since 3.7 */
1363
	int PotentialNullToNonnullParameter = MethodRelated + 884;
1364
	/** @since 3.7 */
1365
	int NonNullParameterInsufficientInfo = MethodRelated + 885;
1366
	/** @since 3.7 */
1367
	int ConflictingTypeEmulation = ImportRelated + 886;
1368
	/** @since 3.7 */
1369
	int IllegalRedefinitionToNullableReturn = MethodRelated + 887;
1370
	/** @since 3.7 */
1371
	int IllegalRedefinitionToNonNullParameter = MethodRelated + 888;
1372
1373
	/**
1343
	 * External problems -- These are problems defined by other plugins
1374
	 * External problems -- These are problems defined by other plugins
1344
	 */
1375
	 */
1345
1376
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java (-1 / +7 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 100-105 Link Here
100
				} else if (paramAnnotations != null) {
101
				} else if (paramAnnotations != null) {
101
					paramAnnotations[i] = Binding.NO_ANNOTATIONS;
102
					paramAnnotations[i] = Binding.NO_ANNOTATIONS;
102
				}
103
				}
104
				// transfer nullness info from the argument to the method:
105
				if ((argument.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0) {
106
					if (this.binding.parameterNonNullness == null)
107
						this.binding.parameterNonNullness = new Boolean[this.arguments.length];
108
					this.binding.parameterNonNullness[i] = Boolean.valueOf((argument.binding.tagBits & TagBits.AnnotationNonNull) != 0);
109
				}
103
			}
110
			}
104
			if (paramAnnotations != null)
111
			if (paramAnnotations != null)
105
				this.binding.setParameterAnnotations(paramAnnotations);
112
				this.binding.setParameterAnnotations(paramAnnotations);
Lines 415-421 Link Here
415
		}
422
		}
416
423
417
		try {
424
		try {
418
			bindArguments();
419
			bindThrownExceptions();
425
			bindThrownExceptions();
420
			resolveJavadoc();
426
			resolveJavadoc();
421
			resolveAnnotations(this.scope, this.annotations, this.binding);
427
			resolveAnnotations(this.scope, this.annotations, this.binding);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java (+7 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 161-166 Link Here
161
			case TypeIds.T_JavaLangSuppressWarnings :
162
			case TypeIds.T_JavaLangSuppressWarnings :
162
				tagBits |= TagBits.AnnotationSuppressWarnings;
163
				tagBits |= TagBits.AnnotationSuppressWarnings;
163
				break;
164
				break;
165
			case TypeIds.T_ConfiguredAnnotationNullable :
166
				tagBits |= TagBits.AnnotationNullable;
167
				break;
168
			case TypeIds.T_ConfiguredAnnotationNonNull :
169
				tagBits |= TagBits.AnnotationNonNull;
170
				break;
164
		}
171
		}
165
		return tagBits;
172
		return tagBits;
166
	}
173
	}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-1 / +20 lines)
Lines 8-14 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
10
 *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
11
 *     Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
11
 *     Stephan Herrmann - Contributions for 
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *     						bug 186342 - [compiler][null]Using annotations for null checking
12
 *******************************************************************************/
14
 *******************************************************************************/
13
package org.eclipse.jdt.internal.compiler.ast;
15
package org.eclipse.jdt.internal.compiler.ast;
14
16
Lines 80-85 Link Here
80
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
82
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
81
			}
83
			}
82
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
84
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
85
			// compare actual null-status against parameter annotations of the called method:
86
			int nullStatus = this.arguments[i].nullStatus(flowInfo);
87
			if (nullStatus != FlowInfo.NON_NULL 
88
					&& this.binding.parameterNonNullness != null
89
					&& this.binding.parameterNonNullness[i].booleanValue()) // if @NonNull is required
90
			{
91
				char[][] annotationName = currentScope.environment().globalOptions.nonNullAnnotationName;
92
				currentScope.problemReporter().possiblyNullToNonNullParameter(this.arguments[i], nullStatus, annotationName[annotationName.length-1]);
93
			}
83
		}
94
		}
84
	}
95
	}
85
	ReferenceBinding[] thrownExceptions;
96
	ReferenceBinding[] thrownExceptions;
Lines 250-255 Link Here
250
	}
261
	}
251
}
262
}
252
public int nullStatus(FlowInfo flowInfo) {
263
public int nullStatus(FlowInfo flowInfo) {
264
	if (this.binding.isValidBinding()) {
265
		// try to retrieve null status of this message send from an annotation of the called method:
266
		long tagBits = this.binding.tagBits;
267
		if ((tagBits & TagBits.AnnotationNonNull) != 0)
268
			return FlowInfo.NON_NULL;
269
		if ((tagBits & TagBits.AnnotationNullable) != 0)
270
			return FlowInfo.POTENTIALLY_NULL;
271
	}
253
	return FlowInfo.UNKNOWN;
272
	return FlowInfo.UNKNOWN;
254
}
273
}
255
274
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java (+7 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
12
13
Lines 89-94 Link Here
89
						if (this.binding != null && this.binding.declaringClass == declaringElement)
90
						if (this.binding != null && this.binding.declaringClass == declaringElement)
90
							this.bits &= ~ASTNode.CanBeStatic;
91
							this.bits &= ~ASTNode.CanBeStatic;
91
					}
92
					}
93
					// leverage null-info from parameter annotations:
94
					long argumentTagBits = this.arguments[i].binding.tagBits;
95
					if ((argumentTagBits & TagBits.AnnotationNullable) != 0)
96
						flowInfo.markPotentiallyNullBit(this.arguments[i].binding);
97
					else if ((argumentTagBits & TagBits.AnnotationNonNull) != 0)
98
						flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
92
				}
99
				}
93
			}
100
			}
94
			if (this.binding.declaringClass instanceof MemberTypeBinding && !this.binding.declaringClass.isStatic()) {
101
			if (this.binding.declaringClass instanceof MemberTypeBinding && !this.binding.declaringClass.isStatic()) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java (-1 / +15 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
10
 *     Stephan Herrmann - Contributions for 
11
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     						bug 186342 - [compiler][null]Using annotations for null checking
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.ast;
14
package org.eclipse.jdt.internal.compiler.ast;
13
15
Lines 40-45 Link Here
40
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
42
		if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
41
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
43
			this.expression.checkNPE(currentScope, flowContext, flowInfo);
42
		}
44
		}
45
		if (this.expression.nullStatus(flowInfo) != FlowInfo.NON_NULL) {
46
			// if we can't prove non-null check against declared null-ness of the enclosing method:
47
			AbstractMethodDeclaration referenceMethod = currentScope.methodScope().referenceMethod();
48
			if (referenceMethod != null) {
49
				MethodBinding method = referenceMethod.binding;
50
				if ((method.tagBits & TagBits.AnnotationNonNull) != 0) {
51
					char[][] annotationName = currentScope.environment().globalOptions.nonNullAnnotationName;
52
					currentScope.problemReporter().possiblyNullFromNonNullMethod(this, this.expression.nullStatus(flowInfo), 
53
																				 annotationName[annotationName.length-1]);
54
				}
55
			}
56
		}
43
	}
57
	}
44
	this.initStateIndex =
58
	this.initStateIndex =
45
		currentScope.methodScope().recordInitializationStates(flowInfo);
59
		currentScope.methodScope().recordInitializationStates(flowInfo);
(-)compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java (+81 lines)
Lines 10-15 Link Here
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contribution for bug 236385
11
 *     Stephan Herrmann  - Contribution for bug 236385
12
 *     Stephan Herrmann  - Contribution for bug 295551
12
 *     Stephan Herrmann  - Contribution for bug 295551
13
 *     Stephan Herrmann -  Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.impl;
15
package org.eclipse.jdt.internal.compiler.impl;
15
16
Lines 106-111 Link Here
106
	public static final String OPTION_ReportNullReference = "org.eclipse.jdt.core.compiler.problem.nullReference"; //$NON-NLS-1$
107
	public static final String OPTION_ReportNullReference = "org.eclipse.jdt.core.compiler.problem.nullReference"; //$NON-NLS-1$
107
	public static final String OPTION_ReportPotentialNullReference = "org.eclipse.jdt.core.compiler.problem.potentialNullReference"; //$NON-NLS-1$
108
	public static final String OPTION_ReportPotentialNullReference = "org.eclipse.jdt.core.compiler.problem.potentialNullReference"; //$NON-NLS-1$
108
	public static final String OPTION_ReportRedundantNullCheck = "org.eclipse.jdt.core.compiler.problem.redundantNullCheck"; //$NON-NLS-1$
109
	public static final String OPTION_ReportRedundantNullCheck = "org.eclipse.jdt.core.compiler.problem.redundantNullCheck"; //$NON-NLS-1$
110
	public static final String OPTION_ReportNullContractViolation = "org.eclipse.jdt.core.compiler.problem.nullContractViolation";  //$NON-NLS-1$
111
	public static final String OPTION_ReportPotentialNullContractViolation = "org.eclipse.jdt.core.compiler.problem.potentialNullContractViolation";  //$NON-NLS-1$
112
	public static final String OPTION_ReportNullContractInsufficientInfo = "org.eclipse.jdt.core.compiler.problem.nullContractInsufficientInfo";  //$NON-NLS-1$
109
	public static final String OPTION_ReportAutoboxing = "org.eclipse.jdt.core.compiler.problem.autoboxing"; //$NON-NLS-1$
113
	public static final String OPTION_ReportAutoboxing = "org.eclipse.jdt.core.compiler.problem.autoboxing"; //$NON-NLS-1$
110
	public static final String OPTION_ReportAnnotationSuperInterface = "org.eclipse.jdt.core.compiler.problem.annotationSuperInterface"; //$NON-NLS-1$
114
	public static final String OPTION_ReportAnnotationSuperInterface = "org.eclipse.jdt.core.compiler.problem.annotationSuperInterface"; //$NON-NLS-1$
111
	public static final String OPTION_ReportMissingOverrideAnnotation = "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation"; //$NON-NLS-1$
115
	public static final String OPTION_ReportMissingOverrideAnnotation = "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation"; //$NON-NLS-1$
Lines 141-146 Link Here
141
	public static final String OPTION_ReportMissingAnnotation = "org.eclipse.jdt.core.compiler.problem.missingAnnotation"; //$NON-NLS-1$
145
	public static final String OPTION_ReportMissingAnnotation = "org.eclipse.jdt.core.compiler.problem.missingAnnotation"; //$NON-NLS-1$
142
	public static final String OPTION_ReportMissingJavadoc = "org.eclipse.jdt.core.compiler.problem.missingJavadoc"; //$NON-NLS-1$
146
	public static final String OPTION_ReportMissingJavadoc = "org.eclipse.jdt.core.compiler.problem.missingJavadoc"; //$NON-NLS-1$
143
147
148
	public static final String OPTION_NullableAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nullable"; //$NON-NLS-1$
149
	public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$
150
	public static final String OPTION_EmulateNullAnnotationTypes = "org.eclipse.jdt.core.compiler.annotation.emulate"; //$NON-NLS-1$
151
	public static final String OPTION_DefaultImportNullAnnotationTypes = "org.eclipse.jdt.core.compiler.annotation.defaultImport"; //$NON-NLS-1$
152
144
	/**
153
	/**
145
	 * Possible values for configurable options
154
	 * Possible values for configurable options
146
	 */
155
	 */
Lines 170-175 Link Here
170
	public static final String NO_TAG = "no_tag";	//$NON-NLS-1$
179
	public static final String NO_TAG = "no_tag";	//$NON-NLS-1$
171
	public static final String ALL_STANDARD_TAGS = "all_standard_tags";	//$NON-NLS-1$
180
	public static final String ALL_STANDARD_TAGS = "all_standard_tags";	//$NON-NLS-1$
172
181
182
	private static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$
183
	private static final char[][] DEFAULT_NULLABLE_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.Nullable".toCharArray()); //$NON-NLS-1$
184
173
	/**
185
	/**
174
	 * Bit mask for configurable problems (error/warning threshold)
186
	 * Bit mask for configurable problems (error/warning threshold)
175
	 * Note: bitmask assumes 3 highest bits to denote irritant group (to allow storing 8 groups of 29 bits each
187
	 * Note: bitmask assumes 3 highest bits to denote irritant group (to allow storing 8 groups of 29 bits each
Lines 243-248 Link Here
243
	public static final int UnusedObjectAllocation = IrritantSet.GROUP2 | ASTNode.Bit4;
255
	public static final int UnusedObjectAllocation = IrritantSet.GROUP2 | ASTNode.Bit4;
244
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
256
	public static final int MethodCanBeStatic = IrritantSet.GROUP2 | ASTNode.Bit5;
245
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
257
	public static final int MethodCanBePotentiallyStatic = IrritantSet.GROUP2 | ASTNode.Bit6;
258
	public static final int NullContractViolation = IrritantSet.GROUP2 | ASTNode.Bit7;
259
	public static final int PotentialNullContractViolation = IrritantSet.GROUP2 | ASTNode.Bit8;
260
	public static final int NullContractInsufficientInfo = IrritantSet.GROUP2 | ASTNode.Bit9;
246
261
247
	// Severity level for handlers
262
	// Severity level for handlers
248
	/** 
263
	/** 
Lines 364-369 Link Here
364
	public boolean includeNullInfoFromAsserts;
379
	public boolean includeNullInfoFromAsserts;
365
	/** Controls whether forced generic type problems get reported  */
380
	/** Controls whether forced generic type problems get reported  */
366
	public boolean reportUnavoidableGenericTypeProblems;
381
	public boolean reportUnavoidableGenericTypeProblems;
382
	/** Fully qualified name of annotation to use as marker for nullable types. */
383
	public char[][] nullableAnnotationName;
384
	/** Fully qualified name of annotation to use as marker for nonnull types. */
385
	public char[][] nonNullAnnotationName;
386
	/** Should null annotation types be emulated by synthetic bindings? */
387
	public boolean emulateNullAnnotationTypes;
388
	/** Should null annotation types be imported by default? */
389
	public boolean defaultImportNullAnnotationTypes;
367
390
368
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
391
	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
369
	public final static String[] warningTokens = {
392
	public final static String[] warningTokens = {
Lines 503-508 Link Here
503
				return OPTION_ReportPotentialNullReference;
526
				return OPTION_ReportPotentialNullReference;
504
			case RedundantNullCheck :
527
			case RedundantNullCheck :
505
				return OPTION_ReportRedundantNullCheck;
528
				return OPTION_ReportRedundantNullCheck;
529
			case NullContractViolation :
530
				return OPTION_ReportNullContractViolation;
531
			case PotentialNullContractViolation :
532
				return OPTION_ReportPotentialNullContractViolation;
533
			case NullContractInsufficientInfo :
534
				return OPTION_ReportNullContractInsufficientInfo;
506
			case AutoBoxing :
535
			case AutoBoxing :
507
				return OPTION_ReportAutoboxing;
536
				return OPTION_ReportAutoboxing;
508
			case AnnotationSuperInterface :
537
			case AnnotationSuperInterface :
Lines 748-753 Link Here
748
			case NullReference :
777
			case NullReference :
749
			case PotentialNullReference :
778
			case PotentialNullReference :
750
			case RedundantNullCheck :
779
			case RedundantNullCheck :
780
			case NullContractViolation :
781
			case PotentialNullContractViolation :
782
			case NullContractInsufficientInfo :
751
				return "null"; //$NON-NLS-1$
783
				return "null"; //$NON-NLS-1$
752
			case FallthroughCase :
784
			case FallthroughCase :
753
				return "fallthrough"; //$NON-NLS-1$
785
				return "fallthrough"; //$NON-NLS-1$
Lines 923-928 Link Here
923
		optionsMap.put(OPTION_ReportNullReference, getSeverityString(NullReference));
955
		optionsMap.put(OPTION_ReportNullReference, getSeverityString(NullReference));
924
		optionsMap.put(OPTION_ReportPotentialNullReference, getSeverityString(PotentialNullReference));
956
		optionsMap.put(OPTION_ReportPotentialNullReference, getSeverityString(PotentialNullReference));
925
		optionsMap.put(OPTION_ReportRedundantNullCheck, getSeverityString(RedundantNullCheck));
957
		optionsMap.put(OPTION_ReportRedundantNullCheck, getSeverityString(RedundantNullCheck));
958
		optionsMap.put(OPTION_ReportNullContractViolation, getSeverityString(NullContractViolation));
959
		optionsMap.put(OPTION_ReportPotentialNullContractViolation, getSeverityString(PotentialNullContractViolation));
960
		optionsMap.put(OPTION_ReportNullContractInsufficientInfo, getSeverityString(NullContractInsufficientInfo));
926
		optionsMap.put(OPTION_SuppressWarnings, this.suppressWarnings ? ENABLED : DISABLED);
961
		optionsMap.put(OPTION_SuppressWarnings, this.suppressWarnings ? ENABLED : DISABLED);
927
		optionsMap.put(OPTION_SuppressOptionalErrors, this.suppressOptionalErrors ? ENABLED : DISABLED);
962
		optionsMap.put(OPTION_SuppressOptionalErrors, this.suppressOptionalErrors ? ENABLED : DISABLED);
928
		optionsMap.put(OPTION_ReportUnhandledWarningToken, getSeverityString(UnhandledWarningToken));
963
		optionsMap.put(OPTION_ReportUnhandledWarningToken, getSeverityString(UnhandledWarningToken));
Lines 943-948 Link Here
943
		optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED);
978
		optionsMap.put(OPTION_IncludeNullInfoFromAsserts, this.includeNullInfoFromAsserts ? ENABLED : DISABLED);
944
		optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
979
		optionsMap.put(OPTION_ReportMethodCanBeStatic, getSeverityString(MethodCanBeStatic));
945
		optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
980
		optionsMap.put(OPTION_ReportMethodCanBePotentiallyStatic, getSeverityString(MethodCanBePotentiallyStatic));
981
		if (this.nullableAnnotationName != null) {
982
			char[] compoundName = CharOperation.concatWith(this.nullableAnnotationName, '.');
983
			optionsMap.put(OPTION_NullableAnnotationName, String.valueOf(compoundName));
984
		}
985
		if (this.nonNullAnnotationName != null) {
986
			char[] compoundName = CharOperation.concatWith(this.nonNullAnnotationName, '.');
987
			optionsMap.put(OPTION_NonNullAnnotationName, String.valueOf(compoundName));
988
		}
989
		optionsMap.put(OPTION_EmulateNullAnnotationTypes, this.emulateNullAnnotationTypes ? ENABLED : DISABLED);
990
		optionsMap.put(OPTION_DefaultImportNullAnnotationTypes, this.defaultImportNullAnnotationTypes ? ENABLED : DISABLED);
946
		return optionsMap;
991
		return optionsMap;
947
	}
992
	}
948
993
Lines 1351-1356 Link Here
1351
		if ((optionValue = optionsMap.get(OPTION_ReportNullReference)) != null) updateSeverity(NullReference, optionValue);
1396
		if ((optionValue = optionsMap.get(OPTION_ReportNullReference)) != null) updateSeverity(NullReference, optionValue);
1352
		if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullReference)) != null) updateSeverity(PotentialNullReference, optionValue);
1397
		if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullReference)) != null) updateSeverity(PotentialNullReference, optionValue);
1353
		if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullCheck)) != null) updateSeverity(RedundantNullCheck, optionValue);
1398
		if ((optionValue = optionsMap.get(OPTION_ReportRedundantNullCheck)) != null) updateSeverity(RedundantNullCheck, optionValue);
1399
		if ((optionValue = optionsMap.get(OPTION_ReportNullContractViolation)) != null) updateSeverity(NullContractViolation, optionValue);
1400
		if ((optionValue = optionsMap.get(OPTION_ReportPotentialNullContractViolation)) != null) updateSeverity(PotentialNullContractViolation, optionValue);
1401
		if ((optionValue = optionsMap.get(OPTION_ReportNullContractInsufficientInfo)) != null) updateSeverity(NullContractInsufficientInfo, optionValue);
1354
		if ((optionValue = optionsMap.get(OPTION_ReportAutoboxing)) != null) updateSeverity(AutoBoxing, optionValue);
1402
		if ((optionValue = optionsMap.get(OPTION_ReportAutoboxing)) != null) updateSeverity(AutoBoxing, optionValue);
1355
		if ((optionValue = optionsMap.get(OPTION_ReportAnnotationSuperInterface)) != null) updateSeverity(AnnotationSuperInterface, optionValue);
1403
		if ((optionValue = optionsMap.get(OPTION_ReportAnnotationSuperInterface)) != null) updateSeverity(AnnotationSuperInterface, optionValue);
1356
		if ((optionValue = optionsMap.get(OPTION_ReportMissingOverrideAnnotation)) != null) updateSeverity(MissingOverrideAnnotation, optionValue);
1404
		if ((optionValue = optionsMap.get(OPTION_ReportMissingOverrideAnnotation)) != null) updateSeverity(MissingOverrideAnnotation, optionValue);
Lines 1485-1490 Link Here
1485
				this.storeAnnotations = false;
1533
				this.storeAnnotations = false;
1486
			}
1534
			}
1487
		}
1535
		}
1536
		if ((optionValue = optionsMap.get(OPTION_NullableAnnotationName)) != null) {
1537
			this.nullableAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1538
		}
1539
		if ((optionValue = optionsMap.get(OPTION_NonNullAnnotationName)) != null) {
1540
			this.nonNullAnnotationName = CharOperation.splitAndTrimOn('.', ((String)optionValue).toCharArray());
1541
		}
1542
		if ((optionValue = optionsMap.get(OPTION_EmulateNullAnnotationTypes)) != null) {
1543
			if (ENABLED.equals(optionValue)) {
1544
				this.emulateNullAnnotationTypes = true;
1545
				// ensure that we actually have annotation names to emulate:
1546
				if (this.nullableAnnotationName == null)
1547
					this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
1548
				if (this.nonNullAnnotationName == null)
1549
					this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
1550
			} else if (DISABLED.equals(optionValue)) {
1551
				this.emulateNullAnnotationTypes = false;
1552
			}
1553
		}
1554
		if ((optionValue = optionsMap.get(OPTION_DefaultImportNullAnnotationTypes)) != null) {
1555
			if (ENABLED.equals(optionValue)) {
1556
				this.defaultImportNullAnnotationTypes = true;
1557
				// ensure that we actually have annotation names to be used for default imports:
1558
				if (this.nullableAnnotationName == null)
1559
					this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
1560
				if (this.nonNullAnnotationName == null)
1561
					this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
1562
			} else if (DISABLED.equals(optionValue)) {
1563
				this.defaultImportNullAnnotationTypes = false;
1564
			}
1565
		}
1488
	}
1566
	}
1489
	public String toString() {
1567
	public String toString() {
1490
		StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
1568
		StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
Lines 1560-1565 Link Here
1560
		buf.append("\n\t- null reference: ").append(getSeverityString(NullReference)); //$NON-NLS-1$
1638
		buf.append("\n\t- null reference: ").append(getSeverityString(NullReference)); //$NON-NLS-1$
1561
		buf.append("\n\t- potential null reference: ").append(getSeverityString(PotentialNullReference)); //$NON-NLS-1$
1639
		buf.append("\n\t- potential null reference: ").append(getSeverityString(PotentialNullReference)); //$NON-NLS-1$
1562
		buf.append("\n\t- redundant null check: ").append(getSeverityString(RedundantNullCheck)); //$NON-NLS-1$
1640
		buf.append("\n\t- redundant null check: ").append(getSeverityString(RedundantNullCheck)); //$NON-NLS-1$
1641
		buf.append("\n\t- null contract violation: ").append(getSeverityString(NullContractViolation)); //$NON-NLS-1$
1642
		buf.append("\n\t- potential null contract vialotation: ").append(getSeverityString(PotentialNullContractViolation)); //$NON-NLS-1$
1643
		buf.append("\n\t- insufficient information for checking null contract: ").append(getSeverityString(NullContractInsufficientInfo)); //$NON-NLS-1$
1563
		buf.append("\n\t- autoboxing: ").append(getSeverityString(AutoBoxing)); //$NON-NLS-1$
1644
		buf.append("\n\t- autoboxing: ").append(getSeverityString(AutoBoxing)); //$NON-NLS-1$
1564
		buf.append("\n\t- annotation super interface: ").append(getSeverityString(AnnotationSuperInterface)); //$NON-NLS-1$
1645
		buf.append("\n\t- annotation super interface: ").append(getSeverityString(AnnotationSuperInterface)); //$NON-NLS-1$
1565
		buf.append("\n\t- missing @Override annotation: ").append(getSeverityString(MissingOverrideAnnotation)); //$NON-NLS-1$
1646
		buf.append("\n\t- missing @Override annotation: ").append(getSeverityString(MissingOverrideAnnotation)); //$NON-NLS-1$
(-)compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java (-3 / +11 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
12
12
package org.eclipse.jdt.internal.compiler.impl;
13
package org.eclipse.jdt.internal.compiler.impl;
Lines 58-66 Link Here
58
	public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation);
59
	public static final IrritantSet UNCHECKED = new IrritantSet(CompilerOptions.UncheckedTypeOperation);
59
	public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess);
60
	public static final IrritantSet UNQUALIFIED_FIELD_ACCESS = new IrritantSet(CompilerOptions.UnqualifiedFieldAccess);
60
61
61
	public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default	
62
	public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // see static initializer below	
62
	public static final IrritantSet COMPILER_DEFAULT_WARNINGS = new IrritantSet(0); // see static initializer below
63
	public static final IrritantSet COMPILER_DEFAULT_WARNINGS = new IrritantSet(0); // see static initializer below
63
	static {
64
	static {
65
		COMPILER_DEFAULT_ERRORS
66
			.set(CompilerOptions.NullContractViolation);
64
		COMPILER_DEFAULT_WARNINGS
67
		COMPILER_DEFAULT_WARNINGS
65
			// group-0 warnings enabled by default
68
			// group-0 warnings enabled by default
66
			.set(
69
			.set(
Lines 98-104 Link Here
98
			// group-2 warnings enabled by default
101
			// group-2 warnings enabled by default
99
			.set(
102
			.set(
100
				CompilerOptions.DeadCode
103
				CompilerOptions.DeadCode
101
				|CompilerOptions.Tasks);
104
				| CompilerOptions.Tasks
105
				| CompilerOptions.PotentialNullContractViolation
106
				| CompilerOptions.NullContractInsufficientInfo);
102
			
107
			
103
		ALL.setAll();
108
		ALL.setAll();
104
		HIDING
109
		HIDING
Lines 107-113 Link Here
107
			.set(CompilerOptions.TypeHiding);
112
			.set(CompilerOptions.TypeHiding);
108
		NULL
113
		NULL
109
			.set(CompilerOptions.PotentialNullReference)
114
			.set(CompilerOptions.PotentialNullReference)
110
			.set(CompilerOptions.RedundantNullCheck);
115
			.set(CompilerOptions.RedundantNullCheck)
116
			.set(CompilerOptions.NullContractViolation)
117
			.set(CompilerOptions.PotentialNullContractViolation)
118
			.set(CompilerOptions.NullContractInsufficientInfo);
111
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
119
		RESTRICTION.set(CompilerOptions.DiscouragedReference);
112
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
120
		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
113
		UNUSED
121
		UNUSED
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (+50 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 553-558 Link Here
553
			isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames) : null,
554
			isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames) : null,
554
			this.environment);
555
			this.environment);
555
556
557
	scanForNullAnnotation(method, result);
558
556
	if (use15specifics)
559
	if (use15specifics)
557
		result.tagBits |= method.getTagBits();
560
		result.tagBits |= method.getTagBits();
558
	result.typeVariables = typeVars;
561
	result.typeVariables = typeVars;
Lines 1086-1091 Link Here
1086
AnnotationBinding[] retrieveAnnotations(Binding binding) {
1089
AnnotationBinding[] retrieveAnnotations(Binding binding) {
1087
	return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment);
1090
	return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment);
1088
}
1091
}
1092
private void scanForNullAnnotation(IBinaryMethod method, MethodBinding result) {
1093
	char[][] nullableAnnotationName = this.environment.globalOptions.nullableAnnotationName;
1094
	char[][] nonNullAnnotationName = this.environment.globalOptions.nonNullAnnotationName;
1095
	if (nullableAnnotationName == null || nonNullAnnotationName == null)
1096
		return; // not configured to use null annotations
1097
1098
	IBinaryAnnotation[] annotations = method.getAnnotations();
1099
	if (annotations != null) {
1100
		for (int i = 0; i < annotations.length; i++) {
1101
			char[] annotationTypeName = annotations[i].getTypeName();
1102
			if (annotationTypeName[0] != 'L')
1103
				continue;
1104
			char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1105
			if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1106
				result.tagBits |= TagBits.AnnotationNonNull;
1107
				return;
1108
			}
1109
			if (CharOperation.equals(typeName, nullableAnnotationName)) {
1110
				result.tagBits |= TagBits.AnnotationNullable;
1111
				return;
1112
			}
1113
		}
1114
	}
1115
1116
	for (int j = 0; j < result.parameters.length; j++) {
1117
		IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j); 
1118
		if (paramAnnotations != null) {
1119
			for (int i = 0; i < paramAnnotations.length; i++) {
1120
				char[] annotationTypeName = paramAnnotations[i].getTypeName();
1121
				if (annotationTypeName[0] != 'L')
1122
					continue;
1123
				char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
1124
				if (CharOperation.equals(typeName, nonNullAnnotationName)) {
1125
					if (result.parameterNonNullness == null)
1126
						result.parameterNonNullness = new Boolean[result.parameters.length];
1127
					result.parameterNonNullness[i] = Boolean.TRUE;
1128
					break;
1129
				} else if (CharOperation.equals(typeName, nullableAnnotationName)) {
1130
					if (result.parameterNonNullness == null)
1131
						result.parameterNonNullness = new Boolean[result.parameters.length];
1132
					result.parameterNonNullness[i] = Boolean.FALSE;
1133
					break;
1134
				}
1135
			}
1136
		}
1137
	}
1138
}
1089
SimpleLookupTable storedAnnotations(boolean forceInitialize) {
1139
SimpleLookupTable storedAnnotations(boolean forceInitialize) {
1090
	if (forceInitialize && this.storedAnnotations == null) {
1140
	if (forceInitialize && this.storedAnnotations == null) {
1091
		if (!this.environment.globalOptions.storeAnnotations)
1141
		if (!this.environment.globalOptions.storeAnnotations)
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java (-7 / +42 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Erling Ellingsen -  patch for bug 125570
10
 *     Erling Ellingsen - patch for bug 125570
11
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
13
package org.eclipse.jdt.internal.compiler.lookup;
13
14
Lines 160-166 Link Here
160
161
161
	// allocate the import array, add java.lang.* by default
162
	// allocate the import array, add java.lang.* by default
162
	int numberOfStatements = this.referenceContext.imports.length;
163
	int numberOfStatements = this.referenceContext.imports.length;
163
	int numberOfImports = numberOfStatements + 1;
164
	int numberOfDefaultImports = 1;
165
	if (this.environment.globalOptions.defaultImportNullAnnotationTypes)
166
		numberOfDefaultImports += 2;
167
	int numberOfImports = numberOfStatements + numberOfDefaultImports;
164
	for (int i = 0; i < numberOfStatements; i++) {
168
	for (int i = 0; i < numberOfStatements; i++) {
165
		ImportReference importReference = this.referenceContext.imports[i];
169
		ImportReference importReference = this.referenceContext.imports[i];
166
		if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
170
		if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
Lines 169-176 Link Here
169
		}
173
		}
170
	}
174
	}
171
	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
175
	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
172
	resolvedImports[0] = getDefaultImports()[0];
176
	ImportBinding[] defaultImports = getDefaultImports(); // consistent number of default imports is ensured in LookupEnvironment.makeNullAnnotationTypeImports()
173
	int index = 1;
177
	for (int i = 0; i < numberOfDefaultImports; i++) {
178
		resolvedImports[i] = defaultImports[i];
179
	}
180
	int index = numberOfDefaultImports;
174
181
175
	nextImport : for (int i = 0; i < numberOfStatements; i++) {
182
	nextImport : for (int i = 0; i < numberOfStatements; i++) {
176
		ImportReference importReference = this.referenceContext.imports[i];
183
		ImportReference importReference = this.referenceContext.imports[i];
Lines 303-308 Link Here
303
		return; // can be called when a field constant is resolved before static imports
310
		return; // can be called when a field constant is resolved before static imports
304
	if (this.referenceContext.imports == null) {
311
	if (this.referenceContext.imports == null) {
305
		this.typeOrPackageCache = new HashtableOfObject(1);
312
		this.typeOrPackageCache = new HashtableOfObject(1);
313
		for (int i = 0; i < this.imports.length; i++) {
314
			// cache default-imported null annotation types:
315
			if (!this.imports[i].onDemand) {
316
				char[][] importName = this.imports[i].compoundName;
317
				this.typeOrPackageCache.put(importName[importName.length-1], this.imports[i].resolvedImport);
318
			}
319
		}
306
		return;
320
		return;
307
	}
321
	}
308
322
Lines 327-335 Link Here
327
			break;
341
			break;
328
		}
342
		}
329
	}
343
	}
344
	int numberOfDefaultImports = 1;
345
	if (this.environment.globalOptions.defaultImportNullAnnotationTypes) {
346
		numberOfDefaultImports += 2;
347
		numberOfImports += 2;
348
	}
330
	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
349
	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
331
	resolvedImports[0] = getDefaultImports()[0];
350
	ImportBinding[] defaultImports = getDefaultImports(); // consistent number of default imports is ensured in LookupEnvironment.makeNullAnnotationTypeImports()
332
	int index = 1;
351
	for (int i = 0; i < numberOfDefaultImports; i++) {
352
		resolvedImports[i] = defaultImports[i];
353
	}
354
355
	int index = numberOfDefaultImports;
333
356
334
	// keep static imports with normal imports until there is a reason to split them up
357
	// keep static imports with normal imports until there is a reason to split them up
335
	// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
358
	// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
Lines 613-619 Link Here
613
		importBinding = missingObject.fPackage;
636
		importBinding = missingObject.fPackage;
614
	}
637
	}
615
638
616
	return this.environment.defaultImports = new ImportBinding[] {new ImportBinding(TypeConstants.JAVA_LANG, true, importBinding, null)};
639
	ImportBinding javaLangImport = new ImportBinding(TypeConstants.JAVA_LANG, true, importBinding, null);
640
	ImportBinding[] nullAnnotationImports = this.environment.makeNullAnnotationTypeImports(); // trigger regardless of option below
641
	if (this.environment.globalOptions.defaultImportNullAnnotationTypes) {
642
		ImportBinding[] allDefaultImports = new ImportBinding[nullAnnotationImports.length+1];// java.lang.* + null-annotations
643
		allDefaultImports[0] = javaLangImport;
644
		System.arraycopy(nullAnnotationImports, 0,
645
						 allDefaultImports, 1,
646
						 nullAnnotationImports.length);
647
		this.environment.defaultImports = allDefaultImports;
648
	} else {
649
		this.environment.defaultImports = new ImportBinding[] {javaLangImport};
650
	}
651
	return this.environment.defaultImports;
617
}
652
}
618
// NOT Public API
653
// NOT Public API
619
public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
654
public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java (+58 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 1314-1319 Link Here
1314
		return this.nameEnvironment.isPackage(null, name);
1315
		return this.nameEnvironment.isPackage(null, name);
1315
	return this.nameEnvironment.isPackage(compoundName, name);
1316
	return this.nameEnvironment.isPackage(compoundName, name);
1316
}
1317
}
1318
1319
private ReferenceBinding makeNullAnnotationType(char[][] compoundName, int typeId) {
1320
	char[][] packageName = CharOperation.subarray(compoundName, 0, compoundName.length-1);
1321
	PackageBinding packageBinding = createPackage(packageName);
1322
	ReferenceBinding typeBinding = packageBinding.getType(compoundName[compoundName.length-1]);
1323
	if (typeBinding != null && typeBinding.isValidBinding())
1324
		this.problemReporter.conflictingTypeEmulation(compoundName); // does not return
1325
1326
	BinaryTypeBinding emulatedType = new BinaryTypeBinding();
1327
	emulatedType.compoundName = compoundName;
1328
	emulatedType.modifiers = ClassFileConstants.AccAnnotation | ClassFileConstants.AccPublic;
1329
	emulatedType.fields = Binding.NO_FIELDS;
1330
	emulatedType.methods = Binding.NO_METHODS;
1331
	emulatedType.memberTypes = Binding.NO_MEMBER_TYPES;
1332
	emulatedType.superclass = getType(TypeConstants.JAVA_LANG_OBJECT);
1333
	emulatedType.superInterfaces = Binding.NO_SUPERINTERFACES;
1334
	emulatedType.fPackage = packageBinding;
1335
	emulatedType.typeVariables = Binding.NO_TYPE_VARIABLES;
1336
	emulatedType.tagBits = TagBits.AreFieldsComplete | TagBits.AreFieldsSorted 
1337
							| TagBits.AreMethodsComplete | TagBits.AreMethodsSorted 
1338
							| TagBits.HasNoMemberTypes | TagBits.TypeVariablesAreConnected
1339
							| TagBits.AnnotationClassRetention 
1340
							| TagBits.AnnotationForMethod | TagBits.AnnotationForParameter ;
1341
	emulatedType.id = typeId;
1342
	
1343
	packageBinding.addType(emulatedType);
1344
1345
	return emulatedType;
1346
}
1347
1348
protected ImportBinding[] makeNullAnnotationTypeImports() {
1349
	char[][] nullableAnnotationName = this.globalOptions.nullableAnnotationName;
1350
	char[][] nonNullAnnotationName = this.globalOptions.nonNullAnnotationName;
1351
	if (nullableAnnotationName == null || nonNullAnnotationName == null) {
1352
		if (this.globalOptions.emulateNullAnnotationTypes || this.globalOptions.defaultImportNullAnnotationTypes)
1353
			// shouldn't happen by construction of CompilerOptions.set(Map)
1354
			this.problemReporter.abortDueToInternalError("Inconsistent null annotation options"); //$NON-NLS-1$
1355
		return new ImportBinding[0];
1356
	}
1357
	// fetch annotation types for emulation and/or default import:
1358
	ReferenceBinding nullableAnnotationType = null;
1359
	ReferenceBinding nonNullAnnotationType = null;
1360
	if (this.globalOptions.emulateNullAnnotationTypes) {
1361
		nullableAnnotationType = makeNullAnnotationType(nullableAnnotationName, TypeIds.T_ConfiguredAnnotationNullable);
1362
		nonNullAnnotationType  = makeNullAnnotationType(nonNullAnnotationName, TypeIds.T_ConfiguredAnnotationNonNull);
1363
	} else if (this.globalOptions.defaultImportNullAnnotationTypes) {
1364
		nullableAnnotationType = getType(nullableAnnotationName);
1365
		nonNullAnnotationType  = getType(nonNullAnnotationName);
1366
	}
1367
	if (this.globalOptions.defaultImportNullAnnotationTypes)
1368
		return new ImportBinding[] {
1369
				new ImportBinding(nullableAnnotationName, false, nullableAnnotationType, null),
1370
				new ImportBinding(nonNullAnnotationName, false, nonNullAnnotationType, null)
1371
		};
1372
	return new ImportBinding[0];
1373
}
1374
1317
// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
1375
// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
1318
public MethodVerifier methodVerifier() {
1376
public MethodVerifier methodVerifier() {
1319
	if (this.verifier == null)
1377
	if (this.verifier == null)
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java (+2 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 28-33 Link Here
28
	public char[] selector;
29
	public char[] selector;
29
	public TypeBinding returnType;
30
	public TypeBinding returnType;
30
	public TypeBinding[] parameters;
31
	public TypeBinding[] parameters;
32
	public Boolean[] parameterNonNullness; // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
31
	public ReferenceBinding[] thrownExceptions;
33
	public ReferenceBinding[] thrownExceptions;
32
	public ReferenceBinding declaringClass;
34
	public ReferenceBinding declaringClass;
33
	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
35
	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java (-1 / +5 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
13
package org.eclipse.jdt.internal.compiler.lookup;
13
14
Lines 152-157 Link Here
152
				// interface I { @Override Object clone(); } does not override Object#clone()
153
				// interface I { @Override Object clone(); } does not override Object#clone()
153
				currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
154
				currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
154
			}
155
			}
156
			checkNullContractCompatibility(currentMethod, inheritedMethod);
155
157
156
			if (!areReturnTypesCompatible(currentMethod, inheritedMethod)
158
			if (!areReturnTypesCompatible(currentMethod, inheritedMethod)
157
					&& (currentMethod.returnType.tagBits & TagBits.HasMissingType) == 0) {
159
					&& (currentMethod.returnType.tagBits & TagBits.HasMissingType) == 0) {
Lines 184-190 Link Here
184
		checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
186
		checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
185
	}
187
	}
186
}
188
}
187
189
protected void checkNullContractCompatibility(MethodBinding currentMethod, MethodBinding inheritedMethod) {
190
	// nothing to do here. Real action happens at 1.5+
191
}
188
public void reportRawReferences(MethodBinding currentMethod, MethodBinding inheritedMethod) {
192
public void reportRawReferences(MethodBinding currentMethod, MethodBinding inheritedMethod) {
189
	// nothing to do here. Real action happens at 1.5+
193
	// nothing to do here. Real action happens at 1.5+
190
}
194
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (+34 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 407-412 Link Here
407
	return false;
408
	return false;
408
}
409
}
409
410
411
protected void checkNullContractCompatibility(MethodBinding currentMethod, MethodBinding inheritedMethod) {
412
	if ((inheritedMethod.tagBits & TagBits.AnnotationNonNull) != 0) {
413
		if ((currentMethod.tagBits & TagBits.AnnotationNullable) != 0) {
414
			AbstractMethodDeclaration methodDecl = currentMethod.sourceMethod();
415
			this.type.scope.problemReporter().illegalRedefinitionToNullableReturn(methodDecl, inheritedMethod.declaringClass, 
416
																			this.environment.globalOptions.nonNullAnnotationName);
417
		}
418
	}
419
	if ((currentMethod.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
420
		currentMethod.tagBits |= (inheritedMethod.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable));
421
422
	if (inheritedMethod.parameterNonNullness != null) {
423
		AbstractMethodDeclaration methodDecl = currentMethod.sourceMethod();
424
		for (int i = 0; i < inheritedMethod.parameterNonNullness.length; i++) {
425
			if (inheritedMethod.parameterNonNullness[i] == Boolean.FALSE) { // promised to accept @Nullable
426
				if (currentMethod.parameterNonNullness == null)
427
					currentMethod.parameterNonNullness = new Boolean[currentMethod.parameters.length];
428
				if (currentMethod.parameterNonNullness[i] == Boolean.TRUE) {
429
					this.type.scope.problemReporter().illegalRedefinitionToNonNullParameter(methodDecl.arguments[i], 
430
																			inheritedMethod.declaringClass, 
431
																			this.environment.globalOptions.nullableAnnotationName);
432
					continue;
433
				} 
434
			}
435
			if (currentMethod.parameterNonNullness[i] == null && inheritedMethod.parameterNonNullness[i] != null) {
436
				currentMethod.parameterNonNullness[i] = inheritedMethod.parameterNonNullness[i];
437
				methodDecl.arguments[i].binding.tagBits |= (currentMethod.parameterNonNullness[i].booleanValue())
438
								? TagBits.AnnotationNonNull : TagBits.AnnotationNullable;
439
			}
440
		}
441
	}
442
}
443
410
void reportRawReferences() {
444
void reportRawReferences() {
411
	CompilerOptions compilerOptions = this.type.scope.compilerOptions();
445
	CompilerOptions compilerOptions = this.type.scope.compilerOptions();
412
	if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5 // shouldn't whine at all
446
	if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5 // shouldn't whine at all
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (-2 / +5 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 1408-1416 Link Here
1408
			}
1409
			}
1409
		}
1410
		}
1410
		// only assign parameters if no problems are found
1411
		// only assign parameters if no problems are found
1411
		if (!foundArgProblem) {
1412
		if (foundArgProblem) {
1413
			methodDecl.binding = null;
1414
		} else {
1412
			method.parameters = newParameters;
1415
			method.parameters = newParameters;
1413
		}
1416
		}
1417
		methodDecl.bindArguments();
1414
	}
1418
	}
1415
1419
1416
	boolean foundReturnTypeProblem = false;
1420
	boolean foundReturnTypeProblem = false;
Lines 1453-1459 Link Here
1453
		}
1457
		}
1454
	}
1458
	}
1455
	if (foundArgProblem) {
1459
	if (foundArgProblem) {
1456
		methodDecl.binding = null;
1457
		method.parameters = Binding.NO_PARAMETERS; // see 107004
1460
		method.parameters = Binding.NO_PARAMETERS; // see 107004
1458
		// nullify type parameter bindings as well as they have a backpointer to the method binding
1461
		// nullify type parameter bindings as well as they have a backpointer to the method binding
1459
		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
1462
		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java (-3 / +7 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 119-128 Link Here
119
	long AnnotationInherited = ASTNode.Bit49L;
120
	long AnnotationInherited = ASTNode.Bit49L;
120
	long AnnotationOverride = ASTNode.Bit50L;
121
	long AnnotationOverride = ASTNode.Bit50L;
121
	long AnnotationSuppressWarnings = ASTNode.Bit51L;
122
	long AnnotationSuppressWarnings = ASTNode.Bit51L;
122
	long AllStandardAnnotationsMask = AnnotationTargetMASK | AnnotationRetentionMASK | AnnotationDeprecated | AnnotationDocumented | AnnotationInherited |  AnnotationOverride | AnnotationSuppressWarnings;
123
	long AnnotationNullable = ASTNode.Bit52L;
124
	long AnnotationNonNull = ASTNode.Bit53L;
125
	long AllStandardAnnotationsMask = AnnotationTargetMASK | AnnotationRetentionMASK | AnnotationDeprecated | AnnotationDocumented 
126
				| AnnotationInherited |  AnnotationOverride | AnnotationSuppressWarnings | AnnotationNullable | AnnotationNonNull;
123
127
124
	long DefaultValueResolved = ASTNode.Bit52L;
128
	long DefaultValueResolved = ASTNode.Bit54L;
125
129
126
	// set when type contains non-private constructor(s)
130
	// set when type contains non-private constructor(s)
127
	long HasNonPrivateConstructor = ASTNode.Bit53L;
131
	long HasNonPrivateConstructor = ASTNode.Bit55L;
128
}
132
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (+4 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
package org.eclipse.jdt.internal.compiler.lookup;
12
13
Lines 89-94 Link Here
89
	
90
	
90
	final int T_JavaUtilCollection = 59;
91
	final int T_JavaUtilCollection = 59;
91
92
93
	final int T_ConfiguredAnnotationNullable = 60;
94
	final int T_ConfiguredAnnotationNonNull = 61;
95
92
	final int NoId = Integer.MAX_VALUE;
96
	final int NoId = Integer.MAX_VALUE;
93
97
94
	public static final int IMPLICIT_CONVERSION_MASK = 0xFF;
98
	public static final int IMPLICIT_CONVERSION_MASK = 0xFF;
(-)compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java (+71 lines)
Lines 9-14 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contribution for bug 236385
11
 *     Stephan Herrmann  - Contribution for bug 236385
12
 *     Stephan Herrmann -  Contribution for bug 186342 - [compiler][null]Using annotations for null checking
12
 *******************************************************************************/
13
 *******************************************************************************/
13
package org.eclipse.jdt.internal.compiler.problem;
14
package org.eclipse.jdt.internal.compiler.problem;
14
15
Lines 81-86 Link Here
81
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
82
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
82
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
83
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
83
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
84
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
85
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
84
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
86
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
85
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
87
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
86
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
88
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
Lines 293-298 Link Here
293
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
295
		case IProblem.NullLocalVariableInstanceofYieldsFalse:
294
			return CompilerOptions.RedundantNullCheck;
296
			return CompilerOptions.RedundantNullCheck;
295
297
298
		case IProblem.DefiniteNullFromNonNullMethod:
299
		case IProblem.DefiniteNullToNonnullParameter:
300
		case IProblem.IllegalRedefinitionToNullableReturn:
301
		case IProblem.IllegalRedefinitionToNonNullParameter:
302
			return CompilerOptions.NullContractViolation;
303
		case IProblem.PotentialNullFromNonNullMethod:
304
		case IProblem.PotentialNullToNonnullParameter:
305
			return CompilerOptions.PotentialNullContractViolation;
306
		case IProblem.NonNullParameterInsufficientInfo:
307
		case IProblem.NonNullReturnInsufficientInfo:
308
			return CompilerOptions.NullContractInsufficientInfo;
309
296
		case IProblem.BoxingConversion :
310
		case IProblem.BoxingConversion :
297
		case IProblem.UnboxingConversion :
311
		case IProblem.UnboxingConversion :
298
			return CompilerOptions.AutoBoxing;
312
			return CompilerOptions.AutoBoxing;
Lines 469-474 Link Here
469
			case CompilerOptions.NullReference :
483
			case CompilerOptions.NullReference :
470
			case CompilerOptions.PotentialNullReference :
484
			case CompilerOptions.PotentialNullReference :
471
			case CompilerOptions.RedundantNullCheck :
485
			case CompilerOptions.RedundantNullCheck :
486
			case CompilerOptions.NullContractViolation :
487
			case CompilerOptions.PotentialNullContractViolation :
488
			case CompilerOptions.NullContractInsufficientInfo :
472
			case CompilerOptions.IncompleteEnumSwitch :
489
			case CompilerOptions.IncompleteEnumSwitch :
473
			case CompilerOptions.FallthroughCase :
490
			case CompilerOptions.FallthroughCase :
474
			case CompilerOptions.OverridingMethodWithoutSuperInvocation :
491
			case CompilerOptions.OverridingMethodWithoutSuperInvocation :
Lines 530-535 Link Here
530
	switch (problemID) {
547
	switch (problemID) {
531
		case IProblem.IsClassPathCorrect :
548
		case IProblem.IsClassPathCorrect :
532
		case IProblem.CorruptedSignature :
549
		case IProblem.CorruptedSignature :
550
		case IProblem.ConflictingTypeEmulation :
533
			return CategorizedProblem.CAT_BUILDPATH;
551
			return CategorizedProblem.CAT_BUILDPATH;
534
552
535
		default :
553
		default :
Lines 1331-1336 Link Here
1331
		importRef.sourceStart,
1349
		importRef.sourceStart,
1332
		importRef.sourceEnd);
1350
		importRef.sourceEnd);
1333
}
1351
}
1352
public void conflictingTypeEmulation(char[][] compoundName) {
1353
	String[] arguments = new String[] {CharOperation.toString(compoundName)};
1354
	this.handle(
1355
		IProblem.ConflictingTypeEmulation,
1356
		arguments,
1357
		arguments,
1358
		ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal, // not configurable
1359
		0, 0);	
1360
}
1334
public void constantOutOfRange(Literal literal, TypeBinding literalType) {
1361
public void constantOutOfRange(Literal literal, TypeBinding literalType) {
1335
	String[] arguments = new String[] {new String(literalType.readableName()), new String(literal.source())};
1362
	String[] arguments = new String[] {new String(literalType.readableName()), new String(literal.source())};
1336
	this.handle(
1363
	this.handle(
Lines 2437-2442 Link Here
2437
		qualifiedTypeReference.sourceStart,
2464
		qualifiedTypeReference.sourceStart,
2438
		qualifiedTypeReference.sourceEnd);
2465
		qualifiedTypeReference.sourceEnd);
2439
}
2466
}
2467
public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] nullableAnnotationName) {
2468
	this.handle(
2469
			IProblem.IllegalRedefinitionToNonNullParameter, 
2470
			new String[] { new String(declaringClass.readableName()), CharOperation.toString(nullableAnnotationName)},
2471
			new String[] { new String(declaringClass.shortReadableName()), new String(nullableAnnotationName[nullableAnnotationName.length-1])},
2472
			argument.sourceStart, 
2473
			argument.sourceEnd);
2474
}
2475
public void illegalRedefinitionToNullableReturn(AbstractMethodDeclaration methodDecl, ReferenceBinding declaringClass, char[][] nonNullAnnotationName) {
2476
	this.handle(
2477
		IProblem.IllegalRedefinitionToNullableReturn, 
2478
		new String[] { new String(declaringClass.readableName()), CharOperation.toString(nonNullAnnotationName)},
2479
		new String[] { new String(declaringClass.shortReadableName()), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])},
2480
		methodDecl.sourceStart, 
2481
		methodDecl.sourceEnd);	
2482
}
2440
public void illegalStaticModifierForMemberType(SourceTypeBinding type) {
2483
public void illegalStaticModifierForMemberType(SourceTypeBinding type) {
2441
	String[] arguments = new String[] {new String(type.sourceName())};
2484
	String[] arguments = new String[] {new String(type.sourceName())};
2442
	this.handle(
2485
	this.handle(
Lines 6078-6083 Link Here
6078
		caseStatement.sourceStart,
6121
		caseStatement.sourceStart,
6079
		caseStatement.sourceEnd);
6122
		caseStatement.sourceEnd);
6080
}
6123
}
6124
public void possiblyNullFromNonNullMethod(ReturnStatement returnStatement, int nullStatus, char[] annotationName) {
6125
	int problemId = IProblem.NonNullReturnInsufficientInfo;
6126
	if ((nullStatus & FlowInfo.NULL) != 0)
6127
		problemId = IProblem.DefiniteNullFromNonNullMethod;
6128
	if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
6129
		problemId = IProblem.PotentialNullFromNonNullMethod;
6130
	String[] arguments = new String[] { String.valueOf(annotationName) };
6131
	this.handle(
6132
		problemId,
6133
		arguments,
6134
		arguments,
6135
		returnStatement.sourceStart,
6136
		returnStatement.sourceEnd);
6137
}
6138
public void possiblyNullToNonNullParameter(Expression argument, int nullStatus, char[] annotationName) {
6139
	int problemId = IProblem.NonNullParameterInsufficientInfo;
6140
	if ((nullStatus & FlowInfo.NULL) != 0)
6141
		problemId = IProblem.DefiniteNullToNonnullParameter;
6142
	else if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
6143
		problemId = IProblem.PotentialNullToNonnullParameter;
6144
	String[] arguments = new String[] { String.valueOf(annotationName) };
6145
	this.handle(
6146
		problemId,
6147
		arguments,
6148
		arguments,
6149
		argument.sourceStart,
6150
		argument.sourceEnd);
6151
}
6081
public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
6152
public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
6082
	this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
6153
	this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
6083
	String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
6154
	String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
(-)compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties (-1 / +14 lines)
Lines 8-14 Link Here
8
# Contributors:
8
# Contributors:
9
#     IBM Corporation - initial API and implementation
9
#     IBM Corporation - initial API and implementation
10
#		Benjamin Muskalla - Contribution for bug 239066
10
#		Benjamin Muskalla - Contribution for bug 239066
11
#		Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
11
#		Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
12
#						bug 185682 - Increment/decrement operators mark local variables as read
13
#				 		bug 186342 - [compiler][null]Using annotations for null checking
12
###############################################################################
14
###############################################################################
13
0 = {0}
15
0 = {0}
14
1 = super cannot be used in java.lang.Object
16
1 = super cannot be used in java.lang.Object
Lines 619-624 Link Here
619
858 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4})
621
858 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4})
620
859 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}>
622
859 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}>
621
623
624
### NULL ANNOTATIONS
625
880 = Null contract violation: returning null from a method declared as @{0}.
626
881 = Potential null contract violation: return value can be null but method is declared as @{0}.
627
882 = Potential null contract violation: insufficient nullness information regarding return value while the method is declared as @{0}.
628
883 = Null contract violation: passing null to a parameter declared as @{0}.
629
884 = Potential null contract violation: potentially passing null to a parameter declared as @{0}.
630
885 = Potential null contract violation: insufficient nullness information regarding a value that is passed to a parameter declared as @{0}.
631
886 = Buildpath problem: emulation of type {0} is requested (for null annotations) but a type of this name exists on the build path.
632
887 = Cannot relax null contract for method return, inherited method from {0} is declared as @{1}.
633
888 = Cannot tighten null contract for parameter, inherited method from {0} declares the parameter as @{1}.
634
622
### ELABORATIONS
635
### ELABORATIONS
623
## Access restrictions
636
## Access restrictions
624
78592 = The type {1} is not accessible due to restriction on classpath entry {0}
637
78592 = The type {1} is not accessible due to restriction on classpath entry {0}
(-)model/org/eclipse/jdt/core/JavaCore.java (+77 lines)
Lines 83-88 Link Here
83
 *     Benjamin Muskalla - added COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD
83
 *     Benjamin Muskalla - added COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD
84
 *     Stephan Herrmann  - added COMPILER_PB_UNUSED_OBJECT_ALLOCATION
84
 *     Stephan Herrmann  - added COMPILER_PB_UNUSED_OBJECT_ALLOCATION
85
 *     Stephan Herrmann  - added COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS
85
 *     Stephan Herrmann  - added COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS
86
 *     Stephan Herrmann  - added COMPILER_PB_NULL_CONTRACT_VIOLATION
87
 *     							 COMPILER_PB_POTENTIAL_NULL_CONTRACT_VIOLATION
88
 *     							 COMPILER_PB_NULL_CONTRACT_INSUFFICIENT_INFO
86
 *******************************************************************************/
89
 *******************************************************************************/
87
90
88
package org.eclipse.jdt.core;
91
package org.eclipse.jdt.core;
Lines 1576-1581 Link Here
1576
	 */
1579
	 */
1577
	public static final String COMPILER_PB_POTENTIAL_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.potentialNullReference"; //$NON-NLS-1$
1580
	public static final String COMPILER_PB_POTENTIAL_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.potentialNullReference"; //$NON-NLS-1$
1578
	/**
1581
	/**
1582
	 * Compiler option ID: Reporting Violations of Null Contracts.
1583
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the 
1584
	 *    following situations is detected:
1585
	 *    <ol>
1586
	 *    <li>a method declared with a nonnull annotation returns an expression that is 
1587
	 *    	  statically known to evaluate to a null value</li>
1588
	 *    <li>an expression that is statically known to evaluate to a null value is passed 
1589
	 *        as an argument in a method call where the corresponding parameter of the called
1590
	 *        method is declared with a nonnull annotation.</li>
1591
	 *    <li>a method that overrides an inherited method declared with a nonnull annotation
1592
	 *        tries to relax that contract by specifying a nullable annotation
1593
	 *        (prohibition of contravariant return).</li>
1594
	 *    <li>a method that overrides an inherited method which has a nullable declaration
1595
	 *        for at least one of its parameters, tries to tighten that null contract by
1596
	 *        specifying a nonnull annotation for its corresponding parameter
1597
	 *        (prohibition of covariant parameters).</li>
1598
	 *    </ol>         
1599
	 * </p>
1600
	 * <dl>
1601
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.nullContractViolation"</code></dd>
1602
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1603
	 * <dt>Default:</dt><dd><code>"error"</code></dd>
1604
	 * </dl>
1605
	 * @since 3.7
1606
	 * @category CompilerOptionID
1607
	 */
1608
	public static final String COMPILER_PB_NULL_CONTRACT_VIOLATION = PLUGIN_ID + ".compiler.problem.nullContractViolation"; //$NON-NLS-1$
1609
	/**
1610
	 * Compiler option ID: Reporting Potential Violations of Null Contracts.
1611
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the 
1612
	 *    following situations is detected:
1613
	 *    <ol>
1614
	 *    <li>a method declared with a nonnull annotation returns an expression that is 
1615
	 *    	  statically known to evaluate to a null value on some flow</li>
1616
	 *    <li>an expression that is statically known to evaluate to a null value on some flow
1617
	 *        is passed as an argument in a method call where the corresponding parameter of 
1618
	 *        the called method is declared with a nonnull annotation.</li>
1619
	 *    </ol>         
1620
	 * </p>
1621
	 * <dl>
1622
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.potentialNullContractViolation"</code></dd>
1623
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1624
	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
1625
	 * </dl>
1626
	 * @since 3.7
1627
	 * @category CompilerOptionID
1628
	 */
1629
	public static final String COMPILER_PB_POTENTIAL_NULL_CONTRACT_VIOLATION = PLUGIN_ID + ".compiler.problem.potentialNullContractViolation"; //$NON-NLS-1$
1630
	/**
1631
	 * Compiler option ID: Reporting Insufficient Information for Analysing Adherence to Null Contracts.
1632
	 * <p>When enabled, the compiler will issue an error or a warning whenever one of the 
1633
	 *    following situations is detected:
1634
	 *    <ol>
1635
	 *    <li>a method declared with a nonnull annotation returns an expression for which 
1636
	 *        insufficient nullness information is available for statically proving that no
1637
	 *        flow will pass a null value at runtime.</li>
1638
	 *    <li>an expression for which insufficient nullness information is available for 
1639
	 *        statically proving that it will never evaluate to a null value at runtime
1640
	 *        is passed as an argument in a method call where the corresponding parameter of 
1641
	 *        the called method is declared with a nonnull annotation.</li>
1642
	 *    </ol>
1643
	 *    Insufficient nullness information is usually a consequence of using other unannotated
1644
	 *    variables or methods.
1645
	 * </p>
1646
	 * <dl>
1647
	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.problem.nullContractInsufficientInfo"</code></dd>
1648
	 * <dt>Possible values:</dt><dd><code>{ "error", "warning", "ignore" }</code></dd>
1649
	 * <dt>Default:</dt><dd><code>"warning"</code></dd>
1650
	 * </dl>
1651
	 * @since 3.7
1652
	 * @category CompilerOptionID
1653
	 */
1654
	public static final String COMPILER_PB_NULL_CONTRACT_INSUFFICIENT_INFO = PLUGIN_ID + ".compiler.problem.nullContractInsufficientInfo"; //$NON-NLS-1$
1655
	/**
1579
	 * Compiler option ID: Reporting Redundant Null Check.
1656
	 * Compiler option ID: Reporting Redundant Null Check.
1580
	 * <p>When enabled, the compiler will issue an error or a warning whenever a
1657
	 * <p>When enabled, the compiler will issue an error or a warning whenever a
1581
	 *    variable that is statically known to hold a null or a non-null value
1658
	 *    variable that is statically known to hold a null or a non-null value
(-)src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java (-2 / +89 lines)
Lines 10-16 Link Here
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contribution for bug 236385
11
 *     Stephan Herrmann  - Contribution for bug 236385
12
 *     Stephan Herrmann  - Contribution for bug 295551
12
 *     Stephan Herrmann  - Contribution for bug 295551
13
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
13
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
14
 *     						bug 185682 - Increment/decrement operators mark local variables as read
15
 *     						bug 186342 - [compiler][null]Using annotations for null checking
14
 *******************************************************************************/
16
 *******************************************************************************/
15
package org.eclipse.jdt.core.tests.compiler.regression;
17
package org.eclipse.jdt.core.tests.compiler.regression;
16
18
Lines 48-54 Link Here
48
	private static final Main MAIN = new Main(null/*outWriter*/, null/*errWriter*/, false/*systemExit*/, null/*options*/, null/*progress*/);
50
	private static final Main MAIN = new Main(null/*outWriter*/, null/*errWriter*/, false/*systemExit*/, null/*options*/, null/*progress*/);
49
51
50
	static {
52
	static {
51
//		TESTS_NAMES = new String[] { "test295_warn_options" };
53
//		TESTS_NAMES = new String[] { "testNullAnnotations" };
52
//		TESTS_NUMBERS = new int[] { 306 };
54
//		TESTS_NUMBERS = new int[] { 306 };
53
//		TESTS_RANGE = new int[] { 298, -1 };
55
//		TESTS_RANGE = new int[] { 298, -1 };
54
	}
56
	}
Lines 1589-1594 Link Here
1589
        "    -classNames <className1[,className2,...]>\n" +
1591
        "    -classNames <className1[,className2,...]>\n" +
1590
        "                         qualified names of binary classes to process\n" +
1592
        "                         qualified names of binary classes to process\n" +
1591
        " \n" +
1593
        " \n" +
1594
        " Null annotation options:\n" +
1595
		"    -nullAnnotations:<suboptions>\n" +
1596
		"                      enable use of annotations for specifying null contracts;\n" +
1597
		"                      <suboptions> is a non-empty, comma-separated list of:\n" +
1598
		"        nullable=<typename>\n" +
1599
		"                      specifies the fully qualified name of an annotation type\n" +
1600
		"                      to be used for marking types whose values include null\n" +
1601
		"        nonnull=<typename>\n" +
1602
		"                      specifies the fully qualified name of an annotation type\n" +
1603
		"                      to be used for marking types whose values cannot be null\n" +
1604
		"        emulate       tells the compiler to emulate the above annotation types\n" +
1605
		"                      although they do not exist on the classpath\n" +
1606
		"        import        tells the compiler to import the above annotation types\n" +
1607
		"                      without specific mention in the sources such that their\n" +
1608
		"                      simple names can be used without explicit imports\n" +
1609
		" \n" +
1592
        " Advanced options:\n" +
1610
        " Advanced options:\n" +
1593
        "    @<file>            read command line arguments from file\n" +
1611
        "    @<file>            read command line arguments from file\n" +
1594
        "    -maxProblems <n>   max number of problems per compilation unit (100 by\n" +
1612
        "    -maxProblems <n>   max number of problems per compilation unit (100 by\n" +
Lines 1793-1798 Link Here
1793
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1811
			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---\"/>\n" + 
1794
			"	</command_line>\n" + 
1812
			"	</command_line>\n" + 
1795
			"	<options>\n" + 
1813
			"	<options>\n" + 
1814
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.defaultImport\" value=\"disabled\"/>\n" + 
1815
			"		<option key=\"org.eclipse.jdt.core.compiler.annotation.emulate\" value=\"disabled\"/>\n" + 
1796
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"disabled\"/>\n" + 
1816
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"disabled\"/>\n" + 
1797
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.5\"/>\n" + 
1817
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.5\"/>\n" + 
1798
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
1818
			"		<option key=\"org.eclipse.jdt.core.compiler.codegen.unusedLocal\" value=\"optimize out\"/>\n" + 
Lines 1850-1860 Link Here
1850
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" + 
1870
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noEffectAssignment\" value=\"warning\"/>\n" + 
1851
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
1871
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
1852
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" + 
1872
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" + 
1873
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullContractInsufficientInfo\" value=\"warning\"/>\n" + 
1874
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullContractViolation\" value=\"error\"/>\n" + 
1853
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" + 
1875
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" + 
1854
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
1876
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
1855
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
1877
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
1856
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1878
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
1857
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1879
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
1880
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullContractViolation\" value=\"warning\"/>\n" + 
1858
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1881
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
1859
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + 
1882
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.rawTypeReference\" value=\"warning\"/>\n" + 
1860
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
1883
			"		<option key=\"org.eclipse.jdt.core.compiler.problem.redundantNullCheck\" value=\"ignore\"/>\n" + 
Lines 12264-12267 Link Here
12264
		"3 problems (1 error, 2 warnings)",
12287
		"3 problems (1 error, 2 warnings)",
12265
		true);
12288
		true);
12266
}
12289
}
12290
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342  -- minimal options passed
12291
public void testNullAnnotations1() {
12292
	this.runNegativeTest(
12293
		new String[] {
12294
			"X.java",
12295
			"public class X {\n" +
12296
			"    @org.eclipse.jdt.annotation.NonNull Object foo(boolean b) {\n" +
12297
			"          return null;\n" +
12298
			"    }\n" +
12299
			"}\n"
12300
		},
12301
		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
12302
		+ " -1.5 -nullAnnotations:emulate -d \"" + OUTPUT_DIR + "\"",
12303
		"",
12304
		"----------\n" + 
12305
		"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 3)\n" + 
12306
		"	return null;\n" + 
12307
		"	^^^^^^^^^^^^\n" + 
12308
		"Null contract violation: returning null from a method declared as @NonNull.\n" +
12309
		"----------\n" + 
12310
		"1 problem (1 error)",
12311
		true);
12312
}
12313
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342  -- full options passed
12314
public void testNullAnnotations2() {
12315
	this.runNegativeTest(
12316
		new String[] {
12317
			"X.java",
12318
			"public class X {\n" +
12319
			"    @NichtNull Object foo(boolean b) {\n" +
12320
			"          return null;\n" +
12321
			"    }\n" +
12322
			"}\n"
12323
		},
12324
		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
12325
		+ " -1.5 -nullAnnotations:nullable=org.foo.Nullish,emulate,import,nonnull=de.foo.NichtNull -d \"" + OUTPUT_DIR + "\"",
12326
		"",
12327
		"----------\n" + 
12328
		"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 3)\n" + 
12329
		"	return null;\n" + 
12330
		"	^^^^^^^^^^^^\n" + 
12331
		"Null contract violation: returning null from a method declared as @NichtNull.\n" +
12332
		"----------\n" + 
12333
		"1 problem (1 error)",
12334
		true);
12335
}
12336
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186342  -- unrecognized sub-option
12337
public void testNullAnnotations3() {
12338
	this.runNegativeTest(
12339
		new String[] {
12340
			"X.java",
12341
			"public class X {\n" +
12342
			"    @NichtNull Object foo(boolean b) {\n" +
12343
			"          return null;\n" +
12344
			"    }\n" +
12345
			"}\n"
12346
		},
12347
		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
12348
		+ " -1.5 -nullAnnotations:wrong -d \"" + OUTPUT_DIR + "\"",
12349
		"",
12350
		"Unrecognized sub-option of -nullAnnotations: wrong,\n" + 
12351
		"legal values are nullable=.., nonnull=.., emulate and import\n",
12352
		true);
12353
}
12267
}
12354
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java (+19 lines)
Lines 9-14 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Benjamin Muskalla - Contribution for bug 239066
10
 *     Benjamin Muskalla - Contribution for bug 239066
11
 *     Stephan Herrmann  - Contribution for bug 236385
11
 *     Stephan Herrmann  - Contribution for bug 236385
12
 *     Stephan Herrmann  - Contribution for Bug 186342 - [compiler][null]Using annotations for null checking
12
 *******************************************************************************/
13
 *******************************************************************************/
13
package org.eclipse.jdt.core.tests.compiler.regression;
14
package org.eclipse.jdt.core.tests.compiler.regression;
14
15
Lines 386-394 Link Here
386
		expectedProblemAttributes.put("CodeSnippetMissingMethod", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
387
		expectedProblemAttributes.put("CodeSnippetMissingMethod", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
387
		expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
388
		expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
388
		expectedProblemAttributes.put("ConflictingImport", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
389
		expectedProblemAttributes.put("ConflictingImport", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
390
		expectedProblemAttributes.put("ConflictingTypeEmulation", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
389
		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
391
		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
390
		expectedProblemAttributes.put("CorruptedSignature", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
392
		expectedProblemAttributes.put("CorruptedSignature", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
391
		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
393
		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
394
		expectedProblemAttributes.put("DefiniteNullFromNonNullMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
395
		expectedProblemAttributes.put("DefiniteNullToNonnullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
392
		expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
396
		expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
393
		expectedProblemAttributes.put("DisallowedTargetForAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
397
		expectedProblemAttributes.put("DisallowedTargetForAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
394
		expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(CategorizedProblem.CAT_RESTRICTION));
398
		expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(CategorizedProblem.CAT_RESTRICTION));
Lines 491-496 Link Here
491
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
495
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
492
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
496
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
493
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
497
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
498
		expectedProblemAttributes.put("IllegalRedefinitionToNullableReturn", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
499
		expectedProblemAttributes.put("IllegalRedefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
494
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
500
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
495
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
501
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
496
		expectedProblemAttributes.put("IllegalUsageOfQualifiedTypeReference", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
502
		expectedProblemAttributes.put("IllegalUsageOfQualifiedTypeReference", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
Lines 697-702 Link Here
697
		expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
703
		expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
698
		expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
704
		expectedProblemAttributes.put("NonGenericType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
699
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
705
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
706
		expectedProblemAttributes.put("NonNullReturnInsufficientInfo", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
707
		expectedProblemAttributes.put("NonNullParameterInsufficientInfo", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
700
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
708
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
701
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
709
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
702
		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
710
		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
Lines 746-751 Link Here
746
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
754
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
747
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
755
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
748
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
756
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
757
		expectedProblemAttributes.put("PotentialNullFromNonNullMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
758
		expectedProblemAttributes.put("PotentialNullToNonnullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
749
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
759
		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
750
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
760
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
751
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
761
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
Lines 1023-1031 Link Here
1023
		expectedProblemAttributes.put("CodeSnippetMissingMethod", SKIP);
1033
		expectedProblemAttributes.put("CodeSnippetMissingMethod", SKIP);
1024
		expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(JavaCore.COMPILER_PB_COMPARING_IDENTICAL));
1034
		expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(JavaCore.COMPILER_PB_COMPARING_IDENTICAL));
1025
		expectedProblemAttributes.put("ConflictingImport", SKIP);
1035
		expectedProblemAttributes.put("ConflictingImport", SKIP);
1036
		expectedProblemAttributes.put("ConflictingTypeEmulation", SKIP);
1026
		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(JavaCore.COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST));
1037
		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(JavaCore.COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST));
1027
		expectedProblemAttributes.put("CorruptedSignature", SKIP);
1038
		expectedProblemAttributes.put("CorruptedSignature", SKIP);
1028
		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(JavaCore.COMPILER_PB_DEAD_CODE));
1039
		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(JavaCore.COMPILER_PB_DEAD_CODE));
1040
		expectedProblemAttributes.put("DefiniteNullFromNonNullMethod", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_VIOLATION));
1041
		expectedProblemAttributes.put("DefiniteNullToNonnullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_VIOLATION));
1029
		expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", SKIP);
1042
		expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", SKIP);
1030
		expectedProblemAttributes.put("DisallowedTargetForAnnotation", SKIP);
1043
		expectedProblemAttributes.put("DisallowedTargetForAnnotation", SKIP);
1031
		expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE));
1044
		expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE));
Lines 1128-1133 Link Here
1128
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1141
		expectedProblemAttributes.put("IllegalPrimitiveOrArrayTypeForEnclosingInstance", SKIP);
1129
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1142
		expectedProblemAttributes.put("IllegalQualifiedEnumConstantLabel", SKIP);
1130
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", SKIP);
1143
		expectedProblemAttributes.put("IllegalQualifiedParameterizedTypeAllocation", SKIP);
1144
		expectedProblemAttributes.put("IllegalRedefinitionToNullableReturn", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_VIOLATION));
1145
		expectedProblemAttributes.put("IllegalRedefinitionToNonNullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_VIOLATION));
1131
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1146
		expectedProblemAttributes.put("IllegalStaticModifierForMemberType", SKIP);
1132
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1147
		expectedProblemAttributes.put("IllegalTypeVariableSuperReference", SKIP);
1133
		expectedProblemAttributes.put("IllegalUsageOfQualifiedTypeReference", SKIP);
1148
		expectedProblemAttributes.put("IllegalUsageOfQualifiedTypeReference", SKIP);
Lines 1334-1339 Link Here
1334
		expectedProblemAttributes.put("NonGenericMethod", SKIP);
1349
		expectedProblemAttributes.put("NonGenericMethod", SKIP);
1335
		expectedProblemAttributes.put("NonGenericType", SKIP);
1350
		expectedProblemAttributes.put("NonGenericType", SKIP);
1336
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1351
		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
1352
		expectedProblemAttributes.put("NonNullReturnInsufficientInfo", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_INSUFFICIENT_INFO));
1353
		expectedProblemAttributes.put("NonNullParameterInsufficientInfo", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_CONTRACT_INSUFFICIENT_INFO));
1337
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1354
		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1338
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1355
		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
1339
		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", SKIP);
1356
		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", SKIP);
Lines 1383-1388 Link Here
1383
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP);
1400
		expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP);
1384
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1401
		expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
1385
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1402
		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
1403
		expectedProblemAttributes.put("PotentialNullFromNonNullMethod", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_CONTRACT_VIOLATION));
1404
		expectedProblemAttributes.put("PotentialNullToNonnullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_CONTRACT_VIOLATION));
1386
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1405
		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
1387
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1406
		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
1388
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
1407
		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java (+624 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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 <sherrmann@gk-software.com> - initial API and implementation 
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
13
import java.util.Map;
14
15
import junit.framework.Test;
16
17
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
18
19
public class NullAnnotationTest extends AbstractComparableTest {
20
21
public NullAnnotationTest(String name) {
22
	super(name);
23
}
24
25
// Static initializer to specify tests subset using TESTS_* static variables
26
// All specified tests which does not belong to the class are skipped...
27
// Only the highest compliance level is run; add the VM argument
28
// -Dcompliance=1.4 (for example) to lower it if needed
29
static {
30
//		TESTS_NAMES = new String[] { "test_nonnull_paramter_005" };
31
//		TESTS_NUMBERS = new int[] { 561 };
32
//		TESTS_RANGE = new int[] { 1, 2049 };
33
}
34
35
public static Test suite() {
36
	return buildComparableTestSuite(testClass());
37
}
38
39
public static Class testClass() {
40
	return NullAnnotationTest.class;
41
}
42
43
// Conditionally augment problem detection settings
44
static boolean setNullRelatedOptions = true;
45
protected Map getCompilerOptions() {
46
    Map defaultOptions = super.getCompilerOptions();
47
    if (setNullRelatedOptions) {
48
	    defaultOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
49
	    defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullReference, CompilerOptions.ERROR);
50
	    defaultOptions.put(CompilerOptions.OPTION_ReportRedundantNullCheck, CompilerOptions.ERROR);
51
		defaultOptions.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
52
		defaultOptions.put(CompilerOptions.OPTION_IncludeNullInfoFromAsserts, CompilerOptions.ENABLED);
53
		
54
		// leave new options at these defaults:
55
//		defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, CompilerOptions.ERROR);
56
//		defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, CompilerOptions.WARNING);
57
//		defaultOptions.put(CompilerOptions.OPTION_ReportNullContractInsufficientInfo, CompilerOptions.WARNING);
58
		
59
		defaultOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.eclipse.jdt.annotation.Nullable");
60
		defaultOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.eclipse.jdt.annotation.NonNull");
61
		defaultOptions.put(CompilerOptions.OPTION_EmulateNullAnnotationTypes, CompilerOptions.ENABLED);
62
		defaultOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED);
63
    }
64
    return defaultOptions;
65
}
66
67
// a non-null argument is checked for null
68
public void test_nonnull_parameter_001() {
69
	runNegativeTest(
70
		new String[] {
71
			"X.java",
72
			  "public class X {\n" +
73
			  "    void foo(@NonNull Object o) {\n" +
74
			  "        if (o != null)\n" +
75
			  "              System.out.print(o.toString());\n" +
76
			  "    }\n" +
77
			  "}\n"},
78
	    "----------\n" + 
79
		"1. ERROR in X.java (at line 3)\n" + 
80
		"	if (o != null)\n" + 
81
		"	    ^\n" + 
82
		"Redundant null check: The variable o cannot be null at this location\n" + 
83
		"----------\n",
84
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
85
}
86
// a non-null argument is dereferenced without a check
87
public void test_nonnull_parameter_002() {
88
	runConformTest(
89
		new String[] {
90
			"X.java",
91
			  "public class X {\n" +
92
			  "    void foo(@NonNull Object o) {\n" +
93
			  "        System.out.print(o.toString());\n" +
94
			  "    }\n" +
95
			  "    public static void main(String... args) {\n" +
96
			  "        new X().foo(\"OK\");\n" +
97
			  "    }\n" +
98
			  "}\n"},
99
	    "OK");
100
}
101
// a nullable argument is dereferenced without a check
102
public void test_nullable_paramter_003() {
103
	runNegativeTest(
104
		new String[] {
105
			"X.java",
106
			  "public class X {\n" +
107
			  "    void foo(@Nullable Object o) {\n" +
108
			  "        System.out.print(o.toString());\n" +
109
			  "    }\n" +
110
			  "}\n"},
111
	    "----------\n" + 
112
		"1. ERROR in X.java (at line 3)\n" + 
113
		"	System.out.print(o.toString());\n" + 
114
		"	                 ^\n" + 
115
		"Potential null pointer access: The variable o may be null at this location\n" + 
116
		"----------\n",
117
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
118
}
119
// passing null to nonnull parameter 
120
public void test_nonnull_paramter_001() {
121
	runNegativeTest(
122
		new String[] {
123
			"X.java",
124
			  "public class X {\n" +
125
			  "    void foo(@NonNull Object o) {\n" +
126
			  "        System.out.print(o.toString());\n" +
127
			  "    }\n" +
128
			  "    void bar() {\n" +
129
			  "        foo(null);\n" +
130
			  "    }\n" +
131
			  "}\n"},
132
		"----------\n" + 
133
		"1. ERROR in X.java (at line 6)\n" + 
134
		"	foo(null);\n" + 
135
		"	    ^^^^\n" + 
136
		"Null contract violation: passing null to a parameter declared as @NonNull.\n" + 
137
		"----------\n",
138
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
139
}
140
// passing potential null to nonnull parameter 
141
public void test_nonnull_paramter_002() {
142
	runConformTest(
143
			new String[] {
144
				"Lib.java",
145
				"public class Lib {\n" +
146
				"    void setObject(@NonNull Object o) { }\n" +
147
				"}\n"
148
			});
149
	runConformTest(
150
		false /* flush output directory */,
151
		new String[] {
152
			"X.java",
153
			  "public class X {\n" +
154
			  "    void bar(Lib l, boolean b) {\n" +
155
			  "        Object o = null;\n" +
156
			  "        if (b) o = new Object();\n" +
157
			  "        l.setObject(o);\n" +
158
			  "    }\n" +
159
			  "}\n"},
160
		null /* no class libraries */,
161
		null /* no custom options */,
162
		"----------\n" + 
163
		"1. WARNING in X.java (at line 5)\n" + 
164
		"	l.setObject(o);\n" + 
165
		"	            ^\n" + 
166
		"Potential null contract violation: potentially passing null to a parameter declared as @NonNull.\n" + 
167
		"----------\n",
168
		"",/* expected output */
169
		"",/* expected error */
170
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
171
}
172
// passing unknown value to nonnull parameter 
173
public void test_nonnull_paramter_003() {
174
	runConformTest(
175
			new String[] {
176
				"Lib.java",
177
				"public class Lib {\n" +
178
				"    void setObject(@NonNull Object o) { }\n" +
179
				"}\n"
180
			});
181
	runConformTest(
182
		false /* flush output directory */,
183
		new String[] {
184
			"X.java",
185
			  "public class X {\n" +
186
			  "    void bar(Lib l, Object o) {\n" +
187
			  "        l.setObject(o);\n" +
188
			  "    }\n" +
189
			  "}\n"},
190
		null /* no class libraries */,
191
		null /* no custom options */,
192
		"----------\n" + 
193
		"1. WARNING in X.java (at line 3)\n" + 
194
		"	l.setObject(o);\n" + 
195
		"	            ^\n" + 
196
		"Potential null contract violation: insufficient nullness information regarding a value that is passed to a parameter declared as @NonNull.\n" + 
197
		"----------\n",
198
		"",/* expected output */
199
		"",/* expected error */
200
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
201
}
202
// a method tries to tighten the null contract, super declares parameter as @Nullable
203
public void test_nonnull_paramter_004() {
204
	runConformTest(
205
		new String[] {
206
			"Lib.java",
207
			"public class Lib {\n" +
208
			"    void foo(@Nullable Object o) { }\n" +
209
			"}\n"
210
		});
211
	runNegativeTest(
212
		false /* flush output directory */,
213
		new String[] {
214
			"X.java",
215
			"public class X extends Lib {\n" +
216
			"    @Override\n" +
217
			"    void foo(@NonNull Object o) { System.out.print(o.toString()); }\n" +
218
			"}\n"
219
		},
220
		// compiler options
221
		null /* no class libraries */,
222
		null /* no custom options */,
223
		"----------\n" + 
224
		"1. ERROR in X.java (at line 3)\n" + 
225
		"	void foo(@NonNull Object o) { System.out.print(o.toString()); }\n" + 
226
		"	                         ^\n" + 
227
		"Cannot tighten null contract for parameter, inherited method from Lib declares the parameter as @Nullable.\n" + 
228
		"----------\n",
229
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
230
}
231
// a method body fails to handle the inherited null contract, super declares parameter as @Nullable
232
public void test_nonnull_paramter_005() {
233
	runConformTest(
234
		new String[] {
235
			"Lib.java",
236
			"public class Lib {\n" +
237
			"    void foo(@Nullable Object o) { }\n" +
238
			"}\n"
239
		});
240
	runNegativeTest(
241
		false /* flush output directory */,
242
		new String[] {
243
			"X.java",
244
			"public class X extends Lib {\n" +
245
			"    @Override\n" +
246
			"    void foo(Object o) {\n" +
247
			"        System.out.print(o.toString());\n" +
248
			"    }\n" +
249
			"}\n"
250
		},
251
		// compiler options
252
		null /* no class libraries */,
253
		null /* no custom options */,
254
		"----------\n" + 
255
		"1. ERROR in X.java (at line 4)\n" + 
256
		"	System.out.print(o.toString());\n" + 
257
		"	                 ^\n" + 
258
		"Potential null pointer access: The variable o may be null at this location\n" + 
259
		"----------\n",
260
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
261
}
262
263
// a nullable return value is dereferenced without a check
264
public void test_nullable_return_001() {
265
	runNegativeTest(
266
		new String[] {
267
			"X.java",
268
			"public class X {\n" +
269
			"    @Nullable Object getObject() { return null; }\n" +
270
			"    void foo() {\n" +
271
			"        Object o = getObject();\n" +
272
			"        System.out.print(o.toString());\n" +
273
			"    }\n" +
274
			"}\n"
275
		},
276
		"----------\n" + 
277
		"1. ERROR in X.java (at line 5)\n" + 
278
		"	System.out.print(o.toString());\n" + 
279
		"	                 ^\n" + 
280
		"Potential null pointer access: The variable o may be null at this location\n" + 
281
		"----------\n",
282
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
283
}
284
// a nullable return value is dereferenced without a check, method is read from .class file
285
public void test_nullable_return_002() {
286
	runConformTest(
287
		new String[] {
288
			"Lib.java",
289
			"public class Lib {\n" +
290
			"    @Nullable Object getObject() { return null; }\n" +
291
			"}\n"
292
		});
293
	runNegativeTest(
294
		false /* flush output directory */,
295
		new String[] {
296
			"X.java",
297
			"public class X {\n" +
298
			"    void foo(Lib l) {\n" +
299
			"        Object o = l.getObject();\n" +
300
			"        System.out.print(o.toString());\n" +
301
			"    }\n" +
302
			"}\n"
303
		},
304
		// compiler options
305
		null /* no class libraries */,
306
		null /* no custom options */,
307
		"----------\n" + 
308
		"1. ERROR in X.java (at line 4)\n" + 
309
		"	System.out.print(o.toString());\n" + 
310
		"	                 ^\n" + 
311
		"Potential null pointer access: The variable o may be null at this location\n" + 
312
		"----------\n",
313
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
314
}
315
// a non-null return value is checked for null, method is read from .class file
316
public void test_nonnull_return_001() {
317
	runConformTest(
318
		new String[] {
319
			"Lib.java",
320
			"public class Lib {\n" +
321
			"    @NonNull Object getObject() { return new Object(); }\n" +
322
			"}\n"
323
		});
324
	runNegativeTest(
325
		false /* flush output directory */,
326
		new String[] {
327
			"X.java",
328
			"public class X {\n" +
329
			"    void foo(Lib l) {\n" +
330
			"        Object o = l.getObject();\n" +
331
			"        if (o != null)\n" +
332
			"            System.out.print(o.toString());\n" +
333
			"    }\n" +
334
			"}\n"
335
		},
336
		// compiler options
337
		null /* no class libraries */,
338
		null /* no custom options */,
339
		"----------\n" + 
340
		"1. ERROR in X.java (at line 4)\n" + 
341
		"	if (o != null)\n" + 
342
		"	    ^\n" + 
343
		"Redundant null check: The variable o cannot be null at this location\n" + 
344
		"----------\n",
345
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
346
}
347
// a non-null method returns null
348
public void test_nonnull_return_003() {
349
	runNegativeTest(
350
		new String[] {
351
			"X.java",
352
			"public class X {\n" +
353
			"    @NonNull Object getObject(boolean b) {\n" +
354
			"        if (b)\n" +
355
			"            return null;\n" + // definite contract violation despite enclosing "if"
356
			"        return new Object();\n" +
357
			"    }\n" +
358
			"}\n"
359
		},
360
		"----------\n" + 
361
		"1. ERROR in X.java (at line 4)\n" + 
362
		"	return null;\n" + 
363
		"	^^^^^^^^^^^^\n" + 
364
		"Null contract violation: returning null from a method declared as @NonNull.\n" + 
365
		"----------\n",
366
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
367
}
368
// a non-null method potentially returns null
369
public void test_nonnull_return_004() {
370
	runNegativeTest(
371
		new String[] {
372
			"X.java",
373
			"public class X {\n" +
374
			"    @NonNull Object getObject(@Nullable Object o) {\n" +
375
			"        return o;\n" + // potential contract violation because 'o' is only potentially null
376
			"    }\n" +
377
			"}\n"
378
		},
379
		"----------\n" + 
380
		"1. WARNING in X.java (at line 3)\n" + 
381
		"	return o;\n" + 
382
		"	^^^^^^^^^\n" + 
383
		"Potential null contract violation: return value can be null but method is declared as @NonNull.\n" + 
384
		"----------\n");
385
}
386
// a non-null method returns its non-null argument
387
public void test_nonnull_return_005() {
388
	Map customOptions = getCompilerOptions();
389
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
390
	runConformTest(
391
		new String[] {
392
			"X.java",
393
			"public class X {\n" +
394
			"    @NonNull Object getObject(@NonNull Object o) {\n" +
395
			"        return o;\n" +
396
			"    }\n" +
397
			"}\n"
398
		},
399
		"",
400
		null/*classLibs*/,
401
		true/*shouldFlushOutputDirectory*/,
402
		null/*vmArguments*/,
403
		customOptions,
404
		null/*compilerRequestor*/);
405
}
406
//a non-null method has insufficient nullness info for its return value
407
public void test_nonnull_return_006() {
408
	runNegativeTest(
409
		new String[] {
410
			"X.java",
411
			"public class X {\n" +
412
			"    @NonNull Object getObject(Object o) {\n" +
413
			"        return o;\n" +
414
			"    }\n" +
415
			"}\n"
416
		},
417
		"----------\n" + 
418
		"1. WARNING in X.java (at line 3)\n" + 
419
		"	return o;\n" + 
420
		"	^^^^^^^^^\n" + 
421
		"Potential null contract violation: insufficient nullness information regarding return value while the method is declared as @NonNull.\n" + 
422
		"----------\n");
423
}
424
// a non-null method returns a non-null return of another method, mixed use of fully qualified name / explicit import
425
public void test_nonnull_return_007() {
426
	Map customOptions = getCompilerOptions();
427
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
428
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable");
429
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
430
	customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.DISABLED);
431
	runConformTest(
432
		new String[] {
433
			"Lib.java",
434
			"public class Lib {\n" +
435
			"    @org.foo.NonNull Object getObject() { return new Object(); }\n" + 	// FQN
436
			"}\n",
437
			"X.java",
438
			"import org.foo.NonNull;\n" +											// explicit import
439
			"public class X {\n" +
440
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
441
			"        return l.getObject();\n" +
442
			"    }\n" +
443
			"}\n"
444
		},
445
		"",
446
		null/*classLibs*/,
447
		true/*shouldFlushOutputDirectory*/,
448
		null/*vmArguments*/,
449
		customOptions,
450
		null/*compilerRequestor*/);
451
}
452
// a non-null method returns a non-null return of another method, use of explicit imports throughout
453
public void test_nonnull_return_008() {
454
	Map customOptions = getCompilerOptions();
455
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
456
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable");
457
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
458
	customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.DISABLED);
459
	runConformTest(
460
		new String[] {
461
			"Lib.java",
462
			"import org.foo.NonNull;\n" +
463
			"public class Lib {\n" +
464
			"    @NonNull Object getObject() { return new Object(); }\n" +
465
			"}\n",
466
			"X.java",
467
			"import org.foo.NonNull;\n" +
468
			"public class X {\n" +
469
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
470
			"        Object o = l.getObject();" +
471
			"        return o;\n" +
472
			"    }\n" +
473
			"}\n"
474
		},
475
		"",
476
		null/*classLibs*/,
477
		true/*shouldFlushOutputDirectory*/,
478
		null/*vmArguments*/,
479
		customOptions,
480
		null/*compilerRequestor*/);
481
}
482
// a non-null method returns a non-null return of another method, default import plus explicit ones
483
public void test_nonnull_return_009() {
484
	Map customOptions = getCompilerOptions();
485
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
486
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "org.foo.Nullable");
487
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "org.foo.NonNull");
488
	customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED);
489
	runConformTest(
490
		new String[] {
491
			"libpack/Lib.java",
492
			"package libpack;\n" +
493
			"public class Lib {\n" +
494
			"    public @NonNull Object getObject() { return new Object(); }\n" +
495
			"}\n",
496
			"X.java",
497
			"import libpack.Lib;\n" +
498
			"public class X {\n" +
499
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
500
			"        return l.getObject();\n" +
501
			"    }\n" +
502
			"}\n"
503
		},
504
		"",
505
		null/*classLibs*/,
506
		true/*shouldFlushOutputDirectory*/,
507
		null/*vmArguments*/,
508
		customOptions,
509
		null/*compilerRequestor*/);
510
}
511
// a non-null method returns a non-null return of another method, default import but unspecified annotation names
512
public void test_nonnull_return_010() {
513
	Map customOptions = getCompilerOptions();
514
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
515
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, null);
516
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, null);
517
	customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED);
518
	runConformTest(
519
		new String[] {
520
			"libpack/Lib.java",
521
			"package libpack;\n" +
522
			"public class Lib {\n" +
523
			"    public @NonNull Object getObject() { return new Object(); }\n" +
524
			"}\n",
525
			"X.java",
526
			"import libpack.Lib;\n" +
527
			"public class X {\n" +
528
			"    @NonNull Object getObject(@NonNull Lib l) {\n" +
529
			"        return l.getObject();\n" +
530
			"    }\n" +
531
			"}\n"
532
		},
533
		"",
534
		null/*classLibs*/,
535
		true/*shouldFlushOutputDirectory*/,
536
		null/*vmArguments*/,
537
		customOptions,
538
		null/*compilerRequestor*/);
539
}
540
// a non-null method returns a non-null return of another method, emulation names conflict with existing types
541
public void test_nonnull_return_011() {
542
	Map customOptions = getCompilerOptions();
543
	customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.ERROR);
544
	customOptions.put(CompilerOptions.OPTION_NullableAnnotationName, "libpack.Lib");
545
	customOptions.put(CompilerOptions.OPTION_NonNullAnnotationName, "libpack.Lib");
546
	customOptions.put(CompilerOptions.OPTION_DefaultImportNullAnnotationTypes, CompilerOptions.ENABLED);
547
	runNegativeTest(
548
		true/*shouldFlushOutputDirectory*/,
549
		new String[] {
550
			"libpack/Lib.java",
551
			"package libpack;\n" +
552
			"public class Lib {\n" +
553
			"}\n",
554
		},
555
		null/*classLibs*/,
556
		customOptions,
557
		"----------\n" + 
558
		"1. ERROR in libpack\\Lib.java (at line 0)\n" + 
559
		"	package libpack;\n" + 
560
		"	^\n" + 
561
		"Buildpath problem: emulation of type libpack.Lib is requested (for null annotations) but a type of this name exists on the build path.\n" + 
562
		"----------\n",
563
		JavacTestOptions.SKIP);
564
}
565
// a method tries to relax the null contract, super declares @NonNull return
566
public void test_nonnull_return_012() {
567
	runConformTest(
568
		new String[] {
569
			"Lib.java",
570
			"public class Lib {\n" +
571
			"    @NonNull Object getObject() { return new Object(); }\n" +
572
			"}\n"
573
		});
574
	runNegativeTest(
575
		false /* flush output directory */,
576
		new String[] {
577
			"X.java",
578
			"public class X extends Lib {\n" +
579
			"    @Override\n" +
580
			"    @Nullable Object getObject() { return null; }\n" +
581
			"}\n"
582
		},
583
		// compiler options
584
		null /* no class libraries */,
585
		null /* no custom options */,
586
		"----------\n" + 
587
		"1. ERROR in X.java (at line 3)\n" + 
588
		"	@Nullable Object getObject() { return null; }\n" + 
589
		"	                 ^^^^^^^^^^^\n" + 
590
		"Cannot relax null contract for method return, inherited method from Lib is declared as @NonNull.\n" + 
591
		"----------\n",
592
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
593
}
594
// a method body violates the inherited null contract, super declares @NonNull return
595
public void test_nonnull_return_013() {
596
	runConformTest(
597
		new String[] {
598
			"Lib.java",
599
			"public class Lib {\n" +
600
			"    @NonNull Object getObject() { return new Object(); }\n" +
601
			"}\n"
602
		});
603
	runNegativeTest(
604
		false /* flush output directory */,
605
		new String[] {
606
			"X.java",
607
			"public class X extends Lib {\n" +
608
			"    @Override\n" +
609
			"    Object getObject() { return null; }\n" +
610
			"}\n"
611
		},
612
		// compiler options
613
		null /* no class libraries */,
614
		null /* no custom options */,
615
		"----------\n" + 
616
		"1. ERROR in X.java (at line 3)\n" + 
617
		"	Object getObject() { return null; }\n" + 
618
		"	                     ^^^^^^^^^^^^\n" + 
619
		"Null contract violation: returning null from a method declared as @NonNull.\n" + 
620
		"----------\n",
621
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
622
}
623
624
}

Return to bug 186342