Merge branch 'master' into integration
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 0328324..2c24d92 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -15,6 +15,7 @@
  *     							bug 349326 - [1.7] new warning for missing try-with-resources
  *     							bug 359721 - [options] add command line option for new warning token "resource"
  *     							bug 186342 - [compiler][null] Using annotations for null checking
+ *								bug 365208 - [compiler][batch] command line options for annotation based null analysis
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
@@ -51,8 +52,33 @@
 	static final String JRE_HOME_DIR = Util.getJREDirectory();
 	private static final Main MAIN = new Main(null/*outWriter*/, null/*errWriter*/, false/*systemExit*/, null/*options*/, null/*progress*/);
 
+	private static final String NONNULL_BY_DEFAULT_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+			"import static java.lang.annotation.ElementType.*;\n" +
+			"import java.lang.annotation.*;\n" +
+			"@Documented\n" +
+			"@Retention(RetentionPolicy.CLASS)\n" +
+			"@Target({ PACKAGE, TYPE, METHOD, CONSTRUCTOR })\n" +
+			"public @interface NonNullByDefault{\n" +
+			"}";
+	private static final String NULLABLE_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+			"import static java.lang.annotation.ElementType.*;\n" +
+			"import java.lang.annotation.*;\n" +
+			"@Documented\n" +
+			"@Retention(RetentionPolicy.CLASS)\n" +
+			"@Target({ METHOD, PARAMETER })\n" +
+			"public @interface Nullable{\n" +
+			"}\n";
+	private static final String NONNULL_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
+			"import static java.lang.annotation.ElementType.*;\n" +
+			"import java.lang.annotation.*;\n" +
+			"@Documented\n" +
+			"@Retention(RetentionPolicy.CLASS)\n" +
+			"@Target({ METHOD, PARAMETER })\n" +
+			"public @interface NonNull{\n" +
+			"}\n";
+
 	static {
-//		TESTS_NAMES = new String[] { "test295_warn_options" };
+//		TESTS_NAMES = new String[] { "test31" };
 //		TESTS_NUMBERS = new int[] { 306 };
 //		TESTS_RANGE = new int[] { 298, -1 };
 	}
@@ -1614,6 +1640,8 @@
         "    -enableJavadoc     consider references in javadoc\n" +
         "    -Xemacs            used to enable emacs-style output in the console.\n" +
         "                       It does not affect the xml log output\n" +
+        "    -nonNullByDefault  for annotation based null analysis assume nonnull\n" + 
+        "                       as the global default\n" + 
         " \n" +
         "    -? -help           print this help message\n" +
         "    -v -version        print compiler version\n" +
@@ -1702,6 +1730,9 @@
         "      nls                  string literal lacking non-nls tag //$NON-NLS-<n>$\n" + 
         "      noEffectAssign     + assignment without effect\n" + 
         "      null                 potential missing or redundant null check\n" + 
+        "      nullAnnot(<annot. names separated by |>) + annotation based null analysis,\n" +
+        "                           nullable|nonnull|nonnullbydefault annotation types\n" +
+        "                           optionally specified using fully qualified names\n" +
         "      nullDereference    + missing null check\n" + 
         "      nullFields    	  + null analysis for fields\n" + 
         "      over-ann             missing @Override annotation (superclass)\n" + 
@@ -12384,4 +12415,315 @@
 		"1 problem (1 warning)", 
 		true);
 }
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot (with args)
+// Null warnings because of annotations - custom annotation types used - challenging various kinds of diagnostics
+public void test312_warn_options() {
+	this.runConformTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import static java.lang.annotation.ElementType.*;\n" +
+				"import java.lang.annotation.*;\n" +
+				"@SuppressWarnings(\"unused\")\n" +
+				"public class X {\n" +
+				"	public void test() { Object o = null; o.toString();}\n" +
+				"  @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+				"    if (o.toString() == \"\"){ return null;}\n" +
+				"    if (o2 == null) {}\n" +
+				"    goo(null).toString();\n" +
+				"	 Object local = null;\n" +
+				"	 o.toString();\n" +
+				"	 return null;\n" +
+				"  }\n" +
+				"  @Nullable Object goo(@NonNull Object o2) {\n" +
+				"    return new Object();\n" +
+				"  }\n" +
+				"  @NonNullByDefault Object hoo(Object o2) {\n" +
+				"    if (o2 == null){}\n" +
+				"    if (o2 == null){\n" +
+				"	    return null;\n" +
+				"	 }\n" +
+				"	 return new Object();\n" +
+				"  }\n" +
+				"}\n" +
+				"@Documented\n" +
+				"@Retention(RetentionPolicy.CLASS)\n" +
+				"@Target({ METHOD, PARAMETER })\n" +
+				"@interface NonNull{\n" +
+				"}\n" +
+				"@Documented\n" +
+				"@Retention(RetentionPolicy.CLASS)\n" +
+				"@Target({ METHOD, PARAMETER })\n" +
+				"@interface Nullable{\n" +
+				"}\n" +
+				"@Documented\n" +
+				"@Retention(RetentionPolicy.CLASS)\n" +
+				"@Target({ PACKAGE, TYPE, METHOD, CONSTRUCTOR })\n" +
+				"@interface NonNullByDefault{\n" +
+				"}"
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "p" + File.separator + "X.java\""
+//		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -1.5"
+		+ " -warn:+nullAnnot(p.Nullable|p.NonNull|p.NonNullByDefault) -warn:+null -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"----------\n" + 
+		"1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" + 
+		"	public void test() { Object o = null; o.toString();}\n" + 
+		"	                                      ^\n" + 
+		"Null pointer access: The variable o can only be null at this location\n" + 
+		"----------\n" + 
+		"2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" + 
+		"	if (o.toString() == \"\"){ return null;}\n" + 
+		"	    ^\n" + 
+		"Potential null pointer access: The variable o may be null at this location\n" + 
+		"----------\n" + 
+		"3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" + 
+		"	if (o.toString() == \"\"){ return null;}\n" + 
+		"	                                ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"4. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	if (o2 == null) {}\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The variable o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"5. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 10)\n" + 
+		"	goo(null).toString();\n" + 
+		"	^^^^^^^^^\n" + 
+		"Potential null pointer access: The method goo(Object) may return null\n" + 
+		"----------\n" + 
+		"6. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 10)\n" + 
+		"	goo(null).toString();\n" + 
+		"	    ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"7. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 13)\n" + 
+		"	return null;\n" + 
+		"	       ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"8. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 19)\n" + 
+		"	if (o2 == null){}\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The variable o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"9. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 20)\n" + 
+		"	if (o2 == null){\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The variable o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"9 problems (9 warnings)", 
+		true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot (no args)
+// Null warnings because of annotations, null spec violations
+public void test313_warn_options() {
+	this.runConformTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"public class X {\n" +
+				"  @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+				"	 return this;\n" +
+				"  }\n" +
+				"}\n" +
+				"class Y extends X {\n" +
+				"    @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+				"}\n",
+				"org/eclipse/jdt/annotation/NonNull.java",
+				NONNULL_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/Nullable.java",
+				NULLABLE_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/NonNullByDefault.java",				
+				NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "p" + File.separator + "X.java\""
+		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -1.5"
+		+ " -warn:+nullAnnot -warn:-null -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"----------\n" + 
+		"1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"The return type is incompatible with the @NonNull return from X.foo(Object, Object)\n" + 
+		"----------\n" + 
+		"2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	                     ^^^^^^\n" + 
+		"Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" + 
+		"----------\n" + 
+		"3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	                               ^^^^^^\n" + 
+		"Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" + 
+		"----------\n" + 
+		"3 problems (3 warnings)", 
+		true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -err option - regression tests to check option nullAnnot
+// Null warnings because of annotations, null spec violations configured as errors
+public void test314_warn_options() {
+	this.runNegativeTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"public class X {\n" +
+				"  @NonNull Object foo(@Nullable Object o, @NonNull Object o2) {\n" +
+				"	 return this;\n" +
+				"  }\n" +
+				"}\n" +
+				"class Y extends X {\n" +
+				"    @Nullable Object foo(Object o, Object o2) { return null; }\n" +
+				"}\n",
+				"org/eclipse/jdt/annotation/NonNull.java",
+				NONNULL_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/Nullable.java",
+				NULLABLE_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/NonNullByDefault.java",				
+				NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "p" + File.separator + "X.java\""
+		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -1.5"
+		+ " -err:+nullAnnot -warn:-null -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"----------\n" + 
+		"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"The return type is incompatible with the @NonNull return from X.foo(Object, Object)\n" + 
+		"----------\n" + 
+		"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	                     ^^^^^^\n" + 
+		"Missing nullable annotation: inherited method from X declares this parameter as @Nullable\n" + 
+		"----------\n" + 
+		"3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	@Nullable Object foo(Object o, Object o2) { return null; }\n" + 
+		"	                               ^^^^^^\n" + 
+		"Missing non-null annotation: inherited method from X declares this parameter as @NonNull\n" + 
+		"----------\n" + 
+		"3 problems (3 errors)", 
+		true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot
+// Null warnings because of annotations, global nonNullByDefault
+public void test315_warn_options() {
+	this.runConformTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"@SuppressWarnings(\"unused\")\n" +
+				"public class X {\n" +
+				"  Object foo(@Nullable Object o, Object o2) {\n" +
+				"    if (o.toString() == \"\"){ return null;}\n" +
+				"    if (o2 == null) {}\n" +
+				"    goo(null).toString();\n" +
+				"	 return null;\n" +
+				"  }\n" +
+				"  @Nullable Object goo(Object o2) {\n" +
+				"    return new Object();\n" +
+				"  }\n" +
+				"  @NonNullByDefault Object hoo(Object o2) {\n" + // redundant
+				"    if (o2 == null)\n" +
+				"	    return null;\n" +
+				"    return this;\n" +
+				"  }\n" +
+				"}\n",
+				"org/eclipse/jdt/annotation/NonNull.java",
+				NONNULL_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/Nullable.java",
+				NULLABLE_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/NonNullByDefault.java",				
+				NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "p" + File.separator + "X.java\""
+		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -1.5"
+		+ " -warn:+nullAnnot -warn:+null -nonNullByDefault -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"----------\n" + 
+		"1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" + 
+		"	if (o.toString() == \"\"){ return null;}\n" + 
+		"	    ^\n" + 
+		"Potential null pointer access: The variable o may be null at this location\n" + 
+		"----------\n" + 
+		"2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 6)\n" + 
+		"	if (o.toString() == \"\"){ return null;}\n" + 
+		"	                                ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"3. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 7)\n" + 
+		"	if (o2 == null) {}\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The variable o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"4. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" + 
+		"	goo(null).toString();\n" + 
+		"	^^^^^^^^^\n" + 
+		"Potential null pointer access: The method goo(Object) may return null\n" + 
+		"----------\n" + 
+		"5. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 8)\n" + 
+		"	goo(null).toString();\n" + 
+		"	    ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"6. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 9)\n" + 
+		"	return null;\n" + 
+		"	       ^^^^\n" + 
+		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
+		"----------\n" + 
+		"7. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 14)\n" + 
+		"	@NonNullByDefault Object hoo(Object o2) {\n" + 
+		"	^^^^^^^^^^^^^^^^^\n" + 
+		"Nullness default is redundant with the global default\n" + 
+		"----------\n" + 
+		"8. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 15)\n" + 
+		"	if (o2 == null)\n" + 
+		"	    ^^\n" + 
+		"Null comparison always yields false: The variable o2 cannot be null at this location\n" + 
+		"----------\n" + 
+		"8 problems (8 warnings)", 
+		true);
+}
+
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=325342
+// -warn option - regression tests to check option nullAnnot
+// option syntax error
+public void test316_warn_options() {
+	this.runNegativeTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"@SuppressWarnings(\"unused\")\n" +
+				"public class X {}\n",
+				"org/eclipse/jdt/annotation/NonNull.java",
+				NONNULL_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/Nullable.java",
+				NULLABLE_ANNOTATION_CONTENT,
+				"org/eclipse/jdt/annotation/NonNullByDefault.java",				
+				NONNULL_BY_DEFAULT_ANNOTATION_CONTENT
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "p" + File.separator + "X.java\""
+		+ " -sourcepath \"" + OUTPUT_DIR + "\""
+		+ " -1.5"
+		+ " -warn:+nullAnnot(foo|bar) -warn:+null -nonNullByDefault -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"Token nullAnnot(foo|bar) is not in the expected format \"nullAnnot(<non null annotation name> | <nullable annotation name> | <non-null by default annotation name>)\"\n", 
+		true);
+}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 89562a4..73c0f03 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -14,6 +14,7 @@
  *     							bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
  *     							bug 295551 - Add option to automatically promote all warnings to errors
  *     							bug 359721 - [options] add command line option for new warning token "resource"
+ *								bug 365208 - [compiler][batch] command line options for annotation based null analysis
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.batch;
 
@@ -2379,6 +2380,10 @@
 					mode = INSIDE_WARNINGS_PROPERTIES;
 					continue;
 				}
+				if (currentArg.equals("-nonNullByDefault")) { //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_NonNullIsDefault, CompilerOptions.ENABLED);
+					continue;
+				}
 				break;
 			case INSIDE_TARGET :
 				if (this.didSpecifyTarget) {
@@ -3409,7 +3414,37 @@
 						CompilerOptions.OPTION_IncludeFieldsInNullAnalysis,
 						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
 				return;
-			} 
+			} else if (token.startsWith("nullAnnot")) { //$NON-NLS-1$
+				String annotationNames = Util.EMPTY_STRING;
+				int start = token.indexOf('(');
+				int end = token.indexOf(')');
+				String nonNullAnnotName = null, nullableAnnotName = null, nonNullByDefaultAnnotName = null;
+				if (isEnabling && start >= 0 && end >= 0 && start < end){
+					annotationNames = token.substring(start+1, end).trim();
+					int separator1 = annotationNames.indexOf('|');
+					if (separator1 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
+					nullableAnnotName = annotationNames.substring(0, separator1).trim();
+					if (nullableAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
+					int separator2 = annotationNames.indexOf('|', separator1 + 1);
+					if (separator2 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
+					nonNullAnnotName = annotationNames.substring(separator1 + 1, separator2).trim();
+					if (nonNullAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
+					nonNullByDefaultAnnotName = annotationNames.substring(separator2 + 1).trim();
+					if (nonNullByDefaultAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_NullableAnnotationName, nullableAnnotName);
+					this.options.put(CompilerOptions.OPTION_NonNullAnnotationName, nonNullAnnotName);
+					this.options.put(CompilerOptions.OPTION_NonNullByDefaultAnnotationName, nonNullByDefaultAnnotName);
+				}
+				this.options.put(
+						CompilerOptions.OPTION_AnnotationBasedNullAnalysis,
+						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+				setSeverity(CompilerOptions.OPTION_ReportNullSpecViolation, severity, isEnabling);
+				setSeverity(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, severity, isEnabling);
+				setSeverity(CompilerOptions.OPTION_ReportNullSpecInsufficientInfo, severity, isEnabling);
+				setSeverity(CompilerOptions.OPTION_ReportRedundantNullAnnotation, severity, isEnabling);
+				return;
+			}
+			
 			break;
 		case 'o' :
 			if (token.equals("over-sync") /*|| token.equals("syncOverride")*/) { //$NON-NLS-1$ 
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index e2e6a74..3f5a8dc 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -12,6 +12,7 @@
 #								bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
 #								bug 295551 - Add option to automatically promote all warnings to errors
 #								bug 359721 - [options] add command line option for new warning token "resource"
+#								bug 365208 - [compiler][batch] command line options for annotation based null analysis
 ###############################################################################
 ### JavaBatchCompiler messages.
 
@@ -19,7 +20,7 @@
 #Format: compiler.name = word1 word2 word3
 compiler.name = Eclipse Compiler for Java(TM)
 #Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
-compiler.version = 0.C30, 3.8.0 M5
+compiler.version = 0.C31, 3.8.0 M5
 compiler.copyright = Copyright IBM Corp 2000, 2011. All rights reserved.
 
 ### progress
@@ -103,6 +104,9 @@
 configure.differentencodings=Found encoding {0}. Different encodings were specified: {1}
 configure.differentencoding=Found encoding {0}. A different encoding was specified: {1}
 
+### null annotations
+configure.invalidNullAnnot = Token {0} is not in the expected format "nullAnnot(<non null annotation name> | <nullable annotation name> | <non-null by default annotation name>)"
+
 ### requestor
 requestor.error = {0}. ERROR in {1}
 requestor.warning = {0}. WARNING in {1}
@@ -247,6 +251,8 @@
 \    -enableJavadoc     consider references in javadoc\n\
 \    -Xemacs            used to enable emacs-style output in the console.\n\
 \                       It does not affect the xml log output\n\
+\    -nonNullByDefault  for annotation based null analysis assume nonnull\n\
+\                       as the global default\n\
 \ \n\
 \    -? -help           print this help message\n\
 \    -v -version        print compiler version\n\
@@ -306,6 +312,9 @@
 \      nls                  string literal lacking non-nls tag //$NON-NLS-<n>$\n\
 \      noEffectAssign     + assignment without effect\n\
 \      null                 potential missing or redundant null check\n\
+\      nullAnnot(<annot. names separated by |>) + annotation based null analysis,\n\
+\                           nullable|nonnull|nonnullbydefault annotation types\n\
+\                           optionally specified using fully qualified names\n\
 \      nullDereference    + missing null check\n\
 \      nullFields    	  + null analysis for fields\n\
 \      over-ann             missing @Override annotation (superclass)\n\
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index d3a8994..31b0774 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -42,11 +42,25 @@
 	</td>
   </tr>
 </table>
+<a name="v_C31"></a>
+<hr><h1>
+Eclipse Platform Build Notes<br>
+Java development tools core</h1>
+Eclipse SDK 3.8.0 - January 22, 2012 - 3.8.0 M5
+<br>
+<h2>What's new in this drop</h2>
+
+<h3>Problem Reports Fixed</h3>
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=369251">369251</a>
+Starved worker threads
+<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=365208">365208</a>
+[compiler][batch] command line options for annotation based null analysis
+
 <a name="v_C30"></a>
 <hr><h1>
 Eclipse Platform Build Notes<br>
 Java development tools core</h1>
-Eclipse SDK 3.8.0 - January 20, 2012 - 3.8.0 M5
+Eclipse SDK 3.8.0 - January 20, 2012
 <br>
 <h2>What's new in this drop</h2>
 <ul>
@@ -109,12 +123,24 @@
 	int NullFieldInstanceofYieldsFalse = Internal + FieldRelated + 677;
 </pre>
 </li>
+<li> New IProblems for messages relating to contradictory or redundant null annotations
+<pre>
+	/** @since 3.8 */
+	int RedundantNullDefaultAnnotation = Internal + 925;
+	/** @since 3.8 */
+	int RedundantNullDefaultAnnotationPackage = Internal + 926;
+	/** @since 3.8 */
+	int RedundantNullDefaultAnnotationType = Internal + 927;
+	/** @since 3.8 */
+	int RedundantNullDefaultAnnotationMethod = Internal + 928;
+	/** @since 3.8 */
+	int ContradictoryNullAnnotations = Internal + 929;
+</pre>
+</li>
 </ul>
 <h3>Problem Reports Fixed</h3>
 <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=361356">361356</a>
 Allow to specify encoding for source attachments
-<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=368152">368152</a>
-ConcurrentModificationException on startup in ExternalFoldersManager.createPendingFolders
 <br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=365582">365582</a>
 FUP of bug 361938: Other error code pattern
 <br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=365662">365662</a>
@@ -1178,7 +1204,6 @@
  * Returns the binding key of the declaring type of the element represented by this binding key. If the binding key
  * does not represent a member or if the member doesn't have a declaring type, returns <code>null</code>.
  * 
- * <p>
  * Note that only binding keys for references to methods and fields
  * are fully supported. The binding keys for declarations will not have type parameters.
  * 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
index 192d097..d615698 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
@@ -122,7 +122,7 @@
 		} while (result.exists());
 		if (scheduleForCreation) {
 			if (this.pendingFolders == null)
-				this.pendingFolders = Collections.synchronizedSet(new HashSet());
+				this.pendingFolders = new HashSet();
 			this.pendingFolders.add(externalFolderPath);
 		}
 		knownFolders.put(externalFolderPath, result);
@@ -166,15 +166,13 @@
 		catch(CoreException e) {
 			throw new JavaModelException(e);
 		}
-		synchronized (this.pendingFolders) {
-			Iterator iterator = this.pendingFolders.iterator();
-			while (iterator.hasNext()) {
-				Object folderPath = iterator.next();
-				try {
-					createLinkFolder((IPath) folderPath, false, externalFoldersProject, monitor);
-				} catch (CoreException e) {
-					Util.log(e, "Error while creating a link for external folder :" + folderPath); //$NON-NLS-1$
-				}
+		Iterator iterator = this.pendingFolders.iterator();
+		while (iterator.hasNext()) {
+			Object folderPath = iterator.next();
+			try {
+				createLinkFolder((IPath) folderPath, false, externalFoldersProject, monitor);
+			} catch (CoreException e) {
+				Util.log(e, "Error while creating a link for external folder :" + folderPath); //$NON-NLS-1$
 			}
 		}
 		this.pendingFolders.clear();