Update jdt.core to I20150317-1130
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 49b0fb1..20cc8b1 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
@@ -27,6 +27,7 @@
  *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis 
  *								Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
  *								Bug 440687 - [compiler][batch][null] improve command line option for external annotations
+ *								Bug 408815 - [batch][null] Add CLI option for COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS
  *     Jesper Steen Moller - Contributions for
  *								bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code
  *								bug 407297 - [1.8][compiler] Control generation of parameter names by option
@@ -79,7 +80,7 @@
 			"import java.lang.annotation.*;\n" +
 			"@Documented\n" +
 			"@Retention(RetentionPolicy.CLASS)\n" +
-			"@Target({ METHOD, PARAMETER })\n" +
+			"@Target({ METHOD, PARAMETER, FIELD })\n" +
 			"public @interface Nullable{\n" +
 			"}\n";
 	private static final String NONNULL_ANNOTATION_CONTENT = "package org.eclipse.jdt.annotation;\n" +
@@ -87,7 +88,7 @@
 			"import java.lang.annotation.*;\n" +
 			"@Documented\n" +
 			"@Retention(RetentionPolicy.CLASS)\n" +
-			"@Target({ METHOD, PARAMETER })\n" +
+			"@Target({ METHOD, PARAMETER, FIELD })\n" +
 			"public @interface NonNull{\n" +
 			"}\n";
 
@@ -1907,6 +1908,7 @@
         "                           errors and warnings\n" + 
         "      switchDefault      + switch statement lacking a default case\n" + 
         "      syncOverride         missing synchronized in synchr. method override\n" + 
+        "      syntacticAnalysis    perform syntax-based null analysis for fields\n" + 
         "      syntheticAccess      synthetic access for innerclass\n" + 
         "      tasks(<tags separated by |>) tasks identified by tags inside comments\n" + 
         "      typeHiding         + type parameter hiding another type\n" + 
@@ -12974,6 +12976,39 @@
 		true);
 }
 
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=408815
+// -warn option - regression tests to check option syntacticAnalysis
+// Null warnings because of annotations, null spec violations, suppressed by null-check
+public void test316b_warn_options() {
+	this.runConformTest(
+		new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"public class X {\n" +
+				"  @Nullable Object f;\n" +
+				"  @NonNull Object foo() {\n" +
+				"    if (this.f != null)\n" +
+				"      return this.f;\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,syntacticAnalysis -proc:none -d \"" + OUTPUT_DIR + "\"",
+		"",
+		"",
+		true);
+}
+
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=374605
 // -warn/-error option : enumSwitchPedantic 
 public void test317_warn_options() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index c2e237c..30c5d06 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -5737,5 +5737,42 @@
 			"class Test2<E extends Test1<E>>{}\n"
 		});
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=425203, [compiler][1.7][inference] ECJ rejects valid code using bounded wildcards 
+public void test425203() {
+	String source = 
+			"import java.util.Arrays;\n" + 
+			"import java.util.List;\n" + 
+			"interface MyFunction<Input, Output> {\n" + 
+			"	Output apply(Input input);\n" + 
+			"}\n" + 
+			"public class Test {\n" + 
+			"	public <Input, Output> List<Output> wrap(MyFunction<? super Input, ? extends Output> function, Input input) {\n" + 
+			"		return Arrays.asList(function.apply(input));\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		System.out.println(\"Done\");\n" + 
+			"	}\n" + 
+			"}";
+	if (this.complianceLevel < ClassFileConstants.JDK1_7) {
+		this.runNegativeTest(
+			new String[] {
+				"Test.java",
+				source,
+			},
+			"----------\n" +
+			"1. WARNING in Test.java (at line 8)\n" + 
+			"	return Arrays.asList(function.apply(input));\n" + 
+			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Type safety: A generic array of capture#2-of ? extends Output is created for a varargs parameter\n" + 
+			"----------\n" +
+			"2. ERROR in Test.java (at line 8)\n" +
+			"	return Arrays.asList(function.apply(input));\n" +
+			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"Type mismatch: cannot convert from List<capture#2-of ? extends Output> to List<Output>\n" +
+			"----------\n");
+	} else {
+		runConformTest(new String[]{ "Test.java", source }, "Done");
+	}
+}
 }
 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
index 22caeb9..fa3587a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
@@ -12,6 +12,7 @@
  *								Bug 424205 - [1.8] Cannot infer type for diamond type with lambda on method invocation
  *								Bug 429203 - [1.8][compiler] NPE in AllocationExpression.binding
  *								Bug 456508 - Unexpected RHS PolyTypeBinding for: <code-snippet>
+ *								Bug 462083 - [1.8][inference] Java 8 generic return type mismatch with interface involving type parameter.
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
@@ -2981,6 +2982,29 @@
 		"Type safety: A generic array of QueryAtom<PGroepAccount,PAccount> is created for a varargs parameter\n" + 
 		"----------\n");
 }
+public void testBug462083() {
+	runConformTest(
+		new String[] {
+			"Java8InterfaceTest.java",
+			"public abstract class Java8InterfaceTest\n" + 
+			"{\n" + 
+			"	public static interface Entity {}\n" + 
+			"\n" + 
+			"	public static interface Service<T1 extends Entity> {}\n" + 
+			"\n" + 
+			"    public static interface ServiceLocator<T2 extends Entity> {}\n" + 
+			"\n" + 
+			"    public static class ConcreteClass<T3 extends Entity, S extends Service<T3>> implements ServiceLocator<T3> {}\n" + 
+			"\n" + 
+			"    protected abstract <T4 extends Entity> ConcreteClass<T4, ?> getParameterized(T4 entity);\n" + 
+			"\n" + 
+			"    protected <T5 extends Entity> ServiceLocator<T5> getInterface(T5 entity)\n" + 
+			"    {\n" + 
+			"    	return getParameterized(entity);\n" + 
+			"    }\n" + 
+			"}\n"
+		});
+}
 public static Class testClass() {
 	return GenericsRegressionTest_1_7.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index db37afe..699683f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -5045,4 +5045,65 @@
 		"The method removeEntity(MyEntity) is undefined for the type new MyTickContext(){}\n" + 
 		"----------\n");
 }
+public void testBug455945() {
+	runConformTest(
+		new String[] {
+			"Test.java",
+			"import java.util.function.BiFunction;\n" + 
+			"import java.util.function.Function;\n" + 
+			"import java.util.function.Predicate;\n" + 
+			"import java.util.stream.Stream;\n" + 
+			"\n" + 
+			"public class Test {\n" + 
+			"\n" + 
+			"    static <T> Tuple2<Seq<T>, Seq<T>> splitAtDoesntCompile(Stream<T> stream, long position) {\n" + 
+			"        return seq(stream)\n" + 
+			"            .zipWithIndex()\n" + 
+			"            .partition(t -> t.v2 < position)\n" + 
+			"            .map((v1, v2) -> tuple(\n" + 
+			"                v1.map(t -> t.v1),\n" + 
+			"                v2.map(t -> t.v1)\n" + 
+			"            ));\n" + 
+			"    }\n" + 
+			"\n" + 
+			"    static <T> Tuple2<Seq<T>, Seq<T>> splitAtCompiles(Stream<T> stream, long position) {\n" + 
+			"        return seq(stream)\n" + 
+			"            .zipWithIndex()\n" + 
+			"            .partition(t -> t.v2 < position)\n" + 
+			"            .map((v1, v2) -> Test.<Seq<T>, Seq<T>>tuple(\n" + 
+			"                v1.map(t -> t.v1),\n" + 
+			"                v2.map(t -> t.v1)\n" + 
+			"            ));\n" + 
+			"    }\n" + 
+			"\n" + 
+			"    static <T> Seq<T> seq(Stream<T> stream) {\n" + 
+			"    	return null;\n" + 
+			"    }\n" + 
+			"\n" + 
+			"    static <T1, T2> Tuple2<T1, T2> tuple(T1 v1, T2 v2) {\n" + 
+			"    	return null;\n" + 
+			"    }\n" + 
+			"}\n" + 
+			"\n" + 
+			"interface I<T> {\n" + 
+			"	T get();\n" + 
+			"	<U> I<U> map(Function<T, U> f);\n" + 
+			"}\n" + 
+			"\n" + 
+			"interface Seq<T> {\n" + 
+			"	Seq<Tuple2<T, Long>> zipWithIndex();\n" + 
+			"	Tuple2<Seq<T>, Seq<T>> partition(Predicate<? super T> predicate);\n" + 
+			"	<R> Seq<R> map(Function<? super T, ? extends R> mapper);\n" + 
+			"}\n" + 
+			"\n" + 
+			"class Tuple2<T1, T2> {\n" + 
+			"	T1 v1;\n" + 
+			"	T2 v2;\n" + 
+			"	\n" + 
+			"	<R> R map(BiFunction<T1, T2, R> function) {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"}\n"
+		});
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
index 68dbd0d..eddb943 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
@@ -7,6 +7,8 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Stephan Herrmann - Contribution for
+ *								Bug 446691 - [1.8][null][compiler] NullPointerException in SingleNameReference.analyseCode
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
@@ -681,7 +683,105 @@
 	},
 	"done");
 }
-
+public void testBug446691_comment5() {
+	runConformTest(new String [] {
+		"Test.java",
+		"import java.util.*;\n" + 
+		"\n" + 
+		"public class Test {\n" + 
+		"  protected final Integer myInt;\n" + 
+		"\n" + 
+		"  public Test() {\n" + 
+		"    myInt = Integer.valueOf(0);\n" + 
+		"    try {\n" + 
+		"      Optional.empty().orElseThrow(() -> new IllegalArgumentException(myInt.toString()));\n" + 
+		"    } catch (IllegalArgumentException e) {\n" + 
+		"      throw new RuntimeException();\n" + 
+		"    }\n" + 
+		"    return;\n" + 
+		"  }\n" + 
+		"}\n"
+	});
+}
+public void testBug446691_comment8() {
+	runConformTest(new String [] {
+		"Boom.java",
+		"public class Boom {\n" + 
+		"  private final String field;\n" + 
+		"  public Boom(String arg) {\n" + 
+		"    this.field = arg;\n" + 
+		"    try {\n" + 
+		"      java.util.function.Supplier<String> supplier = () -> field;\n" + 
+		"    } catch (Exception e) {\n" + 
+		"      \n" + 
+		"    }\n" + 
+		"  }\n" + 
+		"}\n"
+	});
+}
+public void testBug446691_comment14() {
+	runNegativeTest(new String [] {
+		"test/Main.java",
+		"package test;\n" + 
+		"\n" + 
+		"import java.util.logging.Logger;\n" + 
+		"\n" + 
+		"public class Main {\n" + 
+		"\n" + 
+		"	private static final Logger LOG = Logger.getLogger(\"test\");\n" + 
+		"	private final static String value;\n" + 
+		"\n" + 
+		"	static {\n" + 
+		"		try {\n" + 
+		"			LOG.info(() -> String.format(\"Value is: %s\", value));\n" + 
+		"		} catch (final Exception ex) {\n" + 
+		"			throw new ExceptionInInitializerError(ex);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}"
+	},
+	"----------\n" + 
+	"1. ERROR in test\\Main.java (at line 8)\n" + 
+	"	private final static String value;\n" + 
+	"	                            ^^^^^\n" + 
+	"The blank final field value may not have been initialized\n" + 
+	"----------\n" + 
+	"2. ERROR in test\\Main.java (at line 12)\n" + 
+	"	LOG.info(() -> String.format(\"Value is: %s\", value));\n" + 
+	"	                                             ^^^^^\n" + 
+	"The blank final field value may not have been initialized\n" + 
+	"----------\n");
+}
+// error in lambda even if field is assigned later
+public void testBug446691_comment14b() {
+	runNegativeTest(new String [] {
+		"test/Main.java",
+		"package test;\n" + 
+		"\n" + 
+		"import java.util.logging.Logger;\n" + 
+		"\n" + 
+		"public class Main {\n" + 
+		"\n" + 
+		"	private static final Logger LOG = Logger.getLogger(\"test\");\n" + 
+		"	private final static String value;\n" + 
+		"\n" + 
+		"	static {\n" + 
+		"		try {\n" + 
+		"			LOG.info(() -> String.format(\"Value is: %s\", value));\n" + 
+		"		} catch (final Exception ex) {\n" + 
+		"			throw new ExceptionInInitializerError(ex);\n" + 
+		"		}\n" +
+		"		value = \"\";" + 
+		"	}\n" + 
+		"}"
+	},
+	"----------\n" + 
+	"1. ERROR in test\\Main.java (at line 12)\n" + 
+	"	LOG.info(() -> String.format(\"Value is: %s\", value));\n" + 
+	"	                                             ^^^^^\n" + 
+	"The blank final field value may not have been initialized\n" + 
+	"----------\n");
+}
 public static Class testClass() {
 	return LambdaRegressionTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
index d3f5e05..5204ab1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -39,8 +39,8 @@
 @SuppressWarnings({ "unchecked", "rawtypes" })
 public class MethodVerifyTest extends AbstractComparableTest {
 	static {
-//		TESTS_NAMES = new String[] { "testBug406928" };
-//		TESTS_NUMBERS = new int[] { 213 };
+//		TESTS_NAMES = new String[] { "test124", "test124b" };
+//		TESTS_NUMBERS = new int[] { 124 };
 //		TESTS_RANGE = new int[] { 190, -1};
 	}
 
@@ -8642,6 +8642,35 @@
 			"}"},
 			this.complianceLevel <= ClassFileConstants.JDK1_6 ? "ab" : "Stack Overflow");
 }
+// Bug 460993: [compiler] Incremental build not always reports the same errors (type cannot be resolved - indirectly referenced)
+public void test124b() {
+	this.runConformTest(
+		new String[] {
+			"A.java",
+			"public class A {\n" +
+			"  public Object o = \"\";\n" +
+			"  public static void main(String args[]) {\n" +
+			"    X.main(args);\n" +
+			"  }\n" +
+			"}\n",
+			"X.java",
+			"public class X {\n" +
+			"  public static String choose(String one, String two) {\n" +
+			"    return one + X.<String>choose(one, two);\n" +
+			"  }\n" +
+			"  public static <T> T choose(T one, T two) {\n" +
+			"    return two;\n" +
+			"  }\n" +
+			"  public static void main(String args[]) {\n" +
+			"    try {\n" +
+			"        System.out.println(choose(\"a\", \"b\"));\n" +
+			"    } catch (StackOverflowError e) {\n" +
+			"        System.out.println(\"Stack Overflow\");\n" +
+			"    }\n" +
+			"  }\n" +
+			"}"},
+		this.complianceLevel <= ClassFileConstants.JDK1_6 ? "ab" : "Stack Overflow");
+}
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=150655
 // variant
 public void test125() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index 59b69a0..1e3fba1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -4860,12 +4860,7 @@
 		"	       ^^^^\n" + 
 		"Null type mismatch: required \'@NonNull T\' but the provided value is null\n" + 
 		"----------\n" + 
-		"2. ERROR in X.java (at line 10)\n" + 
-		"	void test(Inner<Number> inum) {\n" + 
-		"	                ^^^^^^\n" + 
-		"Null constraint mismatch: The type \'Number\' is not a valid substitute for the type parameter \'@NonNull T\'\n" + 
-		"----------\n" + 
-		"3. ERROR in X.java (at line 11)\n" + 
+		"2. ERROR in X.java (at line 11)\n" + 
 		"	@NonNull Number nnn = inum.process(null); // ERR on argument\n" + 
 		"	                                   ^^^^\n" + 
 		"Null type mismatch: required \'@NonNull Number\' but the provided value is null\n" + 
@@ -7574,11 +7569,6 @@
 		"	@NonNull String s = os.orElse(null);\n" + 
 		"	                    ^^^^^^^^^^^^^^^\n" + 
 		"Contradictory null annotations: method was inferred as \'@NonNull @Nullable String orElse(@NonNull @Nullable String)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
-		"----------\n" + 
-		"7. ERROR in OTest.java (at line 11)\n" + 
-		"	@NonNull String s = os.orElse(null);\n" + 
-		"	                    ^^^^^^^^^^^^^^^\n" + 
-		"Null type mismatch: required \'@NonNull String\' but the provided value is inferred as @Nullable\n" + 
 		"----------\n");
 }
 public void testBug454182() {
@@ -7622,4 +7612,131 @@
 		null,
 		"");
 }
+public void testBug437072() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"X.java",
+			"import org.eclipse.jdt.annotation.*;\n" +
+			"import java.util.List;\n" +
+			"public class X {\n" +
+			"	@NonNull int[][] ints = new int[3][4];\n" +
+			"	@NonNull int[][] test1() { return new int[3][4]; }\n" +
+			"	void test2(@NonNull boolean[][] bools) {\n" +
+			"		@NonNull boolean[][] bools2 = bools;\n" +
+			"	}\n" +
+			"	List<@NonNull int[]> intslist;\n" +
+			"	List<@NonNull int> intlist;\n" +
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 4)\n" + 
+		"	@NonNull int[][] ints = new int[3][4];\n" + 
+		"	^^^^^^^^\n" + 
+		"The nullness annotation @NonNull is not applicable for the primitive type int\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 5)\n" + 
+		"	@NonNull int[][] test1() { return new int[3][4]; }\n" + 
+		"	^^^^^^^^\n" + 
+		"The nullness annotation @NonNull is not applicable for the primitive type int\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 6)\n" + 
+		"	void test2(@NonNull boolean[][] bools) {\n" + 
+		"	           ^^^^^^^^\n" + 
+		"The nullness annotation @NonNull is not applicable for the primitive type boolean\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 7)\n" + 
+		"	@NonNull boolean[][] bools2 = bools;\n" + 
+		"	^^^^^^^^\n" + 
+		"The nullness annotation @NonNull is not applicable for the primitive type boolean\n" + 
+		"----------\n" + 
+		"5. ERROR in X.java (at line 9)\n" + 
+		"	List<@NonNull int[]> intslist;\n" + 
+		"	     ^^^^^^^^\n" + 
+		"The nullness annotation @Nullable is not applicable for the primitive type int\n" + 
+		"----------\n" + 
+		"6. ERROR in X.java (at line 10)\n" + 
+		"	List<@NonNull int> intlist;\n" + 
+		"	              ^^^\n" + 
+		"Syntax error, insert \"Dimensions\" to complete ReferenceType\n" + 
+		"----------\n");
+}
+public void testBug448709() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION, JavaCore.WARNING); // ensure program is runnable
+	runConformTestWithLibs(
+		new String[] {
+			"Test.java",
+			"import java.util.*;\n" + 
+			"import java.util.function.*;\n" + 
+			"import org.eclipse.jdt.annotation.*;\n" + 
+			"\n" + 
+			"public class Test {\n" + 
+			"\n" + 
+			"  /**\n" + 
+			"   * A null-annotated version of {@link Objects#requireNonNull(Object)}.\n" + 
+			"   */\n" + 
+			"  public static final <T> @NonNull T requireNonNull(final @Nullable T obj) {\n" + 
+			"    if (obj == null) throw new NullPointerException();\n" + 
+			"    return obj;\n" + 
+			"  }\n" + 
+			"\n" + 
+			"  /**\n" + 
+			"   * A null-annotated version of {@link Optional#map(Function)}.\n" + 
+			"   */\n" + 
+			"  public static final <T,U> @NonNull Optional<U> map(final @NonNull Optional<T> optional, final Function<@NonNull ? super T,? extends U> mapper) {\n" + 
+			"    if (!optional.isPresent()) return requireNonNull(Optional.empty());\n" + 
+			"    final T source = optional.get();\n" + 
+			"    final U result = mapper.apply(source);\n" +
+			"    System.out.println(source+\"->\"+result);\n" + 
+			"    return requireNonNull(Optional.<U> ofNullable(result));\n" + 
+			"  }\n" + 
+			"\n" + 
+			"  /**\n" + 
+			"   * A method with a {@link NonNull} {@link DefaultLocation#PARAMETER} and {@link DefaultLocation#RETURN_TYPE}.\n" + 
+			"   */\n" + 
+			"  public static final @NonNull Integer testMethod(final @NonNull String s) {\n" + 
+			"    final Integer r = Integer.valueOf(s);\n" + 
+			"    if (r == null) throw new NullPointerException();\n" + 
+			"    return r+1;\n" + 
+			"  }\n" + 
+			"\n" + 
+			"  public static void main(final String[] args) {\n" + 
+			"    final @NonNull Optional<@Nullable String> optNullableString = requireNonNull(Optional.ofNullable(\"1\"));\n" + 
+			"\n" + 
+			"    final Function<@NonNull String,@NonNull Integer> testMethodRef = Test::testMethod;\n" + 
+			"    map(optNullableString, testMethodRef);\n" + 
+			"\n" + 
+			"    map(optNullableString, Test::testMethod); // Error: Null type mismatch at parameter 1: required '@NonNull String' but provided '@Nullable String' via method descriptor Function<String,Integer>.apply(String)\n" +
+			"\n" +
+			"    map(optNullableString, (s) -> Test.testMethod(s));\n" + 
+			"  }\n" + 
+			"\n" + 
+			"}\n"
+		},
+		compilerOptions,
+		"----------\n" + 
+		"1. WARNING in Test.java (at line 39)\n" + 
+		"	map(optNullableString, testMethodRef);\n" + 
+		"	                       ^^^^^^^^^^^^^\n" + 
+		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
+		"----------\n" + 
+		"2. WARNING in Test.java (at line 41)\n" + 
+		"	map(optNullableString, Test::testMethod); // Error: Null type mismatch at parameter 1: required \'@NonNull String\' but provided \'@Nullable String\' via method descriptor Function<String,Integer>.apply(String)\n" + 
+		"	                       ^^^^^^^^^^^^^^^^\n" + 
+		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
+		"----------\n" + 
+		"3. WARNING in Test.java (at line 43)\n" + 
+		"	map(optNullableString, (s) -> Test.testMethod(s));\n" + 
+		"	                       ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
+		"----------\n" + 
+		"4. WARNING in Test.java (at line 43)\n" + 
+		"	map(optNullableString, (s) -> Test.testMethod(s));\n" + 
+		"	                                              ^\n" + 
+		"Null type mismatch (type annotations): required \'@NonNull String\' but this expression has type \'@Nullable String\'\n" + 
+		"----------\n",
+		"1->2\n" +
+		"1->2\n" +
+		"1->2");
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
index dfa4957..9c65b46 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
@@ -7,6 +7,8 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Stephan Herrmann - Contribution for
+ *								Bug 461250 - ArrayIndexOutOfBoundsException in SourceTypeBinding.fields
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.dom;
 
@@ -16,6 +18,7 @@
 import java.io.IOException;
 import java.io.Writer;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.dom.AST;
@@ -406,4 +409,24 @@
 			fileY.delete();
 		}
 	}
+
+	public void testBug461250() {
+		String source =
+				"class QH<T> implements QR.Q {\n" +
+				"  QR.Q q;\n" +
+				"  @V(v = A, d = \"\") Map p;\n" +
+				"}\n";
+		Map options = JavaCore.getOptions();
+		JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setCompilerOptions(options);
+		parser.setKind(ASTParser.K_COMPILATION_UNIT);
+		parser.setSource(source.toCharArray());
+		parser.setResolveBindings(true);
+		String[] emptyStringArray = new String[0];
+		parser.setEnvironment(emptyStringArray, emptyStringArray, emptyStringArray, true /* includeRunningVMBootclasspath */);
+		parser.setUnitName("dontCare");
+		ASTNode ast = parser.createAST(null);
+		assertTrue("should have parsed a CUD", ast instanceof CompilationUnit);
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
index 88fc382..9d4bd69 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
@@ -4938,7 +4938,7 @@
  * 
  * @throws JavaModelException
  */
-public void testBug425601_001() throws JavaModelException {
+public void _testBug425601_001() throws JavaModelException {
 	this.workingCopy = getWorkingCopy("/Converter18/src/testBug425601_001/Outer.java",
 			true/* resolve */);
 	String contents = "package testBug425601_001;\n" +
@@ -4983,7 +4983,7 @@
  * 
  * @throws JavaModelException
  */
-public void testBug425601_002() throws JavaModelException {
+public void _testBug425601_002() throws JavaModelException {
 	this.workingCopy = getWorkingCopy("/Converter18/src/testBug425601_002/Outer.java",
 			true/* resolve */);
 	String contents = "package testBug425601_002;\n" +
@@ -5109,4 +5109,32 @@
 		assertTrue("Test Failed", false);
 	}
 }
+/**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=443232
+ * @bug Bug 443232 IAE in ASTNode.setSourceRange with broken code
+ * @throws JavaModelException
+ */
+public void testBug443232() throws JavaModelException {
+	String contents =
+			"package test443232;\n" +
+			"public class E21 {\n" + 
+			"	{private int[] nums;\n" + 
+			"	void foo() {\n" + 
+			"        nums\n" + 
+			"	}\n" + 
+			"}";
+	this.workingCopy = getWorkingCopy("/Converter18/src/test443232/E21.java", contents, false/*computeProblems*/);
+	IJavaProject javaProject = this.workingCopy.getJavaProject();
+
+	final ASTParser parser = ASTParser.newParser(AST.JLS8);
+	parser.setResolveBindings(false);
+	parser.setProject(javaProject);
+	parser.setIgnoreMethodBodies(false);
+	ASTRequestor requestor = new ASTRequestor() {};
+	try {
+		parser.createASTs(new ICompilationUnit[] {this.workingCopy}, new String[0], requestor, null);
+	} catch (IllegalArgumentException e) {
+		assertTrue("Test Failed", false);
+	}
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
index 674f204..a9eef33 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
@@ -10,8 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.model;
 
-import junit.framework.Test;
-
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IncrementalProjectBuilder;
@@ -19,12 +18,24 @@
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaModelMarker;
 import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.util.ExternalAnnotationUtil;
+import org.eclipse.jdt.core.util.ExternalAnnotationUtil.MergeStrategy;
 import org.osgi.framework.Bundle;
 
+import junit.framework.Test;
+
 public class ExternalAnnotations17Test extends ExternalAnnotations18Test {
 
 
@@ -163,4 +174,204 @@
 		}, new int[] { 8 });
 	}
 
+	// ===== Full round trip: detect problem - annotated - detect problem change =====
+
+	public void testAnnotateFieldOfNested() throws Exception {
+		myCreateJavaProject("TestLibs");
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				"package libs;\n" + 
+				"\n" +
+				"public interface Lib1 {\n" +
+				"	public static interface Nested {\n" + 
+				"		String one = \"1\";\n" + 
+				"	}\n" + 
+				"}\n"
+			}, null);
+
+		// acquire source AST:
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		String test1Content = "package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull String test0() {\n" + 
+				"		return Lib1.Nested.one;\n" + 
+				"	}\n" +
+				"}\n";
+		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java", test1Content,
+						true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setSource(cu);
+		parser.setResolveBindings(true);
+		parser.setStatementsRecovery(false);
+		parser.setBindingsRecovery(false);
+		CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+		IProblem[] problems = unit.getProblems();
+		assertProblems(problems, new String[] {
+				"Pb(912) Null type safety: The expression of type 'String' needs unchecked conversion to conform to '@NonNull String'",
+		}, new int[] { 8 });
+		
+		// find type binding:
+		int start = test1Content.indexOf("one");
+		ASTNode name = NodeFinder.perform(unit, start, 0);
+		assertTrue("should be simple name", name.getNodeType() == ASTNode.SIMPLE_NAME);
+		IVariableBinding fieldBinding = (IVariableBinding) ((SimpleName)name).resolveBinding();
+		
+		// find annotation file (not yet existing):
+		IFile annotationFile = ExternalAnnotationUtil.getAnnotationFile(this.project, fieldBinding.getDeclaringClass(), null);
+		assertFalse("file should not exist", annotationFile.exists());
+		assertEquals("file path", "/TestLibs/annots/libs/Lib1$Nested.eea", annotationFile.getFullPath().toString());
+
+		// annotate:
+		String originalSignature = ExternalAnnotationUtil.extractGenericTypeSignature(fieldBinding.getVariableDeclaration().getType());
+		ExternalAnnotationUtil.annotateMember("libs/Lib1$Nested", annotationFile,
+				"one",
+				originalSignature,
+				"L1java/lang/String;",
+				MergeStrategy.OVERWRITE_ANNOTATIONS, null);
+		assertTrue("file should exist", annotationFile.exists());
+
+		// check that the error is gone:
+		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertNoProblems(reconciled.getProblems());		
+	}
+
+
+	public void testAnnotateFieldWithParameterizedType() throws Exception {
+		myCreateJavaProject("TestLibs");
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				"package libs;\n" + 
+				"\n" +
+				"public class Lib1<T> {\n" +
+				"	public Lib1<T> one;\n" +
+				"}\n"
+			}, null);
+
+		// acquire source AST:
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		String test1Content = "package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull Lib1<String> test0(Lib1<String> stringLib) {\n" + 
+				"		return stringLib.one;\n" + 
+				"	}\n" +
+				"}\n";
+		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java", test1Content,
+						true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setSource(cu);
+		parser.setResolveBindings(true);
+		parser.setStatementsRecovery(false);
+		parser.setBindingsRecovery(false);
+		CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+		IProblem[] problems = unit.getProblems();
+		assertProblems(problems, new String[] {
+				"Pb(912) Null type safety: The expression of type 'Lib1<String>' needs unchecked conversion to conform to '@NonNull Lib1<String>'",
+		}, new int[] { 8 });
+		
+		// find type binding:
+		int start = test1Content.indexOf("one");
+		ASTNode name = NodeFinder.perform(unit, start, 0);
+		assertTrue("should be simple name", name.getNodeType() == ASTNode.SIMPLE_NAME);
+		IVariableBinding fieldBinding = (IVariableBinding) ((SimpleName)name).resolveBinding();
+		
+		// find annotation file (not yet existing):
+		IFile annotationFile = ExternalAnnotationUtil.getAnnotationFile(this.project, fieldBinding.getDeclaringClass(), null);
+		assertFalse("file should not exist", annotationFile.exists());
+		assertEquals("file path", "/TestLibs/annots/libs/Lib1.eea", annotationFile.getFullPath().toString());
+
+		// annotate:
+		String originalSignature = ExternalAnnotationUtil.extractGenericTypeSignature(fieldBinding.getVariableDeclaration().getType());
+		ExternalAnnotationUtil.annotateMember("libs/Lib1", annotationFile,
+				"one", 
+				originalSignature, 
+				"L0libs/Lib1<TT;>;", 
+				MergeStrategy.OVERWRITE_ANNOTATIONS, null);
+		assertTrue("file should exist", annotationFile.exists());
+
+		// check that the error is even worse now:
+		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		problems = reconciled.getProblems();
+		assertProblems(problems, new String[] {
+				"Pb(933) Null type mismatch: required '@NonNull Lib1<String>' but the provided value is specified as @Nullable",
+		}, new int[] { 8 });
+	}
+
+	public void testAnnotateMethodReturn() throws Exception {
+		myCreateJavaProject("TestLibs");
+		String lib1Content = 
+				"package libs;\n" + 
+				"\n" +
+				"public interface Lib1<T> {\n" +
+				"	public Lib1<T> getLib();\n" +
+				"}\n";
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				lib1Content
+			}, null);
+
+		// type check sources:
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java",
+				"package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull Lib1<String> test0(Lib1<String> stringLib) {\n" + 
+				"		return stringLib.getLib();\n" + 
+				"	}\n" +
+				"}\n",
+				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		IProblem[] problems = reconciled.getProblems();
+		assertProblems(problems, new String[] {
+				"Pb(912) Null type safety: The expression of type 'Lib1<String>' needs unchecked conversion to conform to '@NonNull Lib1<String>'",
+		}, new int[] { 8 });
+
+		// acquire library AST:
+		IType type = this.project.findType("libs.Lib1");
+		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setSource(libWorkingCopy);
+		parser.setResolveBindings(true);
+		parser.setStatementsRecovery(false);
+		parser.setBindingsRecovery(false);
+		CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+		libWorkingCopy.discardWorkingCopy();
+		
+		// find method binding:
+		int start = lib1Content.indexOf("getLib");
+		ASTNode name = NodeFinder.perform(unit, start, 0);
+		assertTrue("should be simple name", name.getNodeType() == ASTNode.SIMPLE_NAME);
+		ASTNode method = name.getParent();
+		IMethodBinding methodBinding = ((MethodDeclaration)method).resolveBinding();
+		
+		// find annotation file (not yet existing):
+		IFile annotationFile = ExternalAnnotationUtil.getAnnotationFile(this.project, methodBinding.getDeclaringClass(), null);
+		assertFalse("file should not exist", annotationFile.exists());
+		assertEquals("file path", "/TestLibs/annots/libs/Lib1.eea", annotationFile.getFullPath().toString());
+
+		// annotate:
+		String originalSignature = ExternalAnnotationUtil.extractGenericSignature(methodBinding);
+		ExternalAnnotationUtil.annotateMember("libs/Lib1", annotationFile,
+				"getLib", 
+				originalSignature, 
+				"()L1libs/Lib1<TT;>;", 
+				MergeStrategy.OVERWRITE_ANNOTATIONS, null);
+		assertTrue("file should exist", annotationFile.exists());
+
+		// check that the error has gone:
+		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertNoProblems(reconciled.getProblems());
+	}
+
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 1a89994..059530b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -17,6 +17,7 @@
 
 import junit.framework.Test;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IncrementalProjectBuilder;
@@ -33,12 +34,22 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.SimpleName;
 import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
 import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.core.util.ExternalAnnotationUtil;
+import org.eclipse.jdt.core.util.ExternalAnnotationUtil.MergeStrategy;
 import org.eclipse.jdt.internal.core.ClasspathAttribute;
 import org.osgi.framework.Bundle;
 
@@ -216,7 +227,7 @@
 		IClasspathAttribute[] extraAttributes = new IClasspathAttribute[] { new ClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, externalAnnotationPath) };
 		IClasspathEntry entry = JavaCore.newLibraryEntry(
 				new Path(jarPath),
-				null/*src attach*/,
+				new Path('/'+javaProject.getProject().getName()+"/src.zip"),
 				null/*src attach root*/,
 				null/*access rules*/,
 				extraAttributes,
@@ -794,4 +805,146 @@
 		}
 	}
 
+	// ===== Full round trip: detect problem - annotated - detect problem change =====
+
+	public void testAnnotateFieldWithParameterizedType() throws Exception {
+		myCreateJavaProject("TestLibs");
+		String lib1Content =
+				"package libs;\n" + 
+				"\n" +
+				"public abstract class Lib1<T> {\n" +
+				"	public Lib1<T> one;\n" +
+				"	public abstract T get();\n" +
+				"}\n";
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				lib1Content
+			}, null);
+
+		// type check sources:
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java",
+				"package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull String test0(Lib1<String> stringLib) {\n" + 
+				"		return stringLib.one.get();\n" + 
+				"	}\n" +
+				"}\n",
+				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(955) Null type safety (type annotations): The expression of type 'String' needs unchecked conversion to conform to '@NonNull String'",
+		}, new int[] { 8 });
+
+		// acquire library AST:
+		IType type = this.project.findType("libs.Lib1");
+		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setSource(libWorkingCopy);
+		parser.setResolveBindings(true);
+		parser.setStatementsRecovery(false);
+		parser.setBindingsRecovery(false);
+		CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+		libWorkingCopy.discardWorkingCopy();
+		
+		// find type binding:
+		int start = lib1Content.indexOf("one");
+		ASTNode name = NodeFinder.perform(unit, start, 0);
+		assertTrue("should be simple name", name.getNodeType() == ASTNode.SIMPLE_NAME);
+		IVariableBinding fieldBinding = (IVariableBinding) ((SimpleName)name).resolveBinding();
+		
+		// find annotation file (not yet existing):
+		IFile annotationFile = ExternalAnnotationUtil.getAnnotationFile(this.project, fieldBinding.getDeclaringClass(), null);
+		assertFalse("file should not exist", annotationFile.exists());
+		assertEquals("file path", "/TestLibs/annots/libs/Lib1.eea", annotationFile.getFullPath().toString());
+
+		// annotate:
+		String originalSignature = ExternalAnnotationUtil.extractGenericTypeSignature(fieldBinding.getVariableDeclaration().getType());
+		ExternalAnnotationUtil.annotateMember("libs/Lib1", annotationFile,
+				"one", 
+				originalSignature, 
+				"Llibs/Lib1<T0T;>;", 
+				MergeStrategy.OVERWRITE_ANNOTATIONS, null);
+		assertTrue("file should exist", annotationFile.exists());
+
+		// check that the error is even worse now:
+		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
+		}, new int[] { 8 });
+	}
+	
+
+	public void testAnnotateMethodParameter() throws Exception {
+		myCreateJavaProject("TestLibs");
+		String lib1Content =
+				"package libs;\n" + 
+				"\n" +
+				"public abstract class Lib1<T,U> {\n" +
+				"	public abstract void take(Lib1<X,U> lx);\n" +
+				"	public static class X {}\n" +
+				"}\n";
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				lib1Content
+			}, null);
+
+		// type check sources:
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java",
+				"package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	void test0(Lib1<Lib1.X,@Nullable String> xLib1, Lib1<Lib1.@Nullable X,@NonNull String> xLib2) {\n" + 
+				"		xLib1.take(xLib2);\n" + 
+				"	}\n" +
+				"}\n",
+				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(953) Null type mismatch (type annotations): required 'Lib1<Lib1.X,@Nullable String>' but this expression has type 'Lib1<Lib1.@Nullable X,@NonNull String>'",
+		}, new int[] { 7 });
+
+		// acquire library AST:
+		IType type = this.project.findType("libs.Lib1");
+		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
+		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		parser.setSource(libWorkingCopy);
+		parser.setResolveBindings(true);
+		parser.setStatementsRecovery(false);
+		parser.setBindingsRecovery(false);
+		CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+		libWorkingCopy.discardWorkingCopy();
+		
+		// find type binding:
+		int start = lib1Content.indexOf("take");
+		ASTNode name = NodeFinder.perform(unit, start, 0);
+		assertTrue("should be simple name", name.getNodeType() == ASTNode.SIMPLE_NAME);
+		ASTNode method = name.getParent();
+		IMethodBinding methodBinding = ((MethodDeclaration)method).resolveBinding();
+		
+		// find annotation file (not yet existing):
+		IFile annotationFile = ExternalAnnotationUtil.getAnnotationFile(this.project, methodBinding.getDeclaringClass(), null);
+		assertFalse("file should not exist", annotationFile.exists());
+		assertEquals("file path", "/TestLibs/annots/libs/Lib1.eea", annotationFile.getFullPath().toString());
+
+		// annotate:
+		String originalSignature = ExternalAnnotationUtil.extractGenericSignature(methodBinding);
+		ExternalAnnotationUtil.annotateMember("libs/Lib1", annotationFile,
+				"take", 
+				originalSignature, 
+				"(Llibs/Lib1<L0libs/Lib1$X;T1U;>;)V", // <- two annotations: @Nullable X and @NonNull U
+				MergeStrategy.OVERWRITE_ANNOTATIONS, null);
+		assertTrue("file should exist", annotationFile.exists());
+
+		// check that the error is even worse now:
+		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertNoProblems(reconciled.getProblems());
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
index 9df7ed8..f780f76 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
@@ -4638,6 +4638,47 @@
 	}
 }
 
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=461025
+//[1.8][search] Constructor reference not found in search
+public void testBug461025_001() throws CoreException {
+this.workingCopies = new ICompilationUnit[1];
+this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+		"@FunctionalInterface\n" +
+		"interface Y<T> {\n" +
+		"    T get();\n" +
+		"}\n" +
+		"\n" +
+		"public class X {\n" +
+		"	public X() {}\n" +
+		"	public X(int i) {}\n" +
+		"\n" +
+		"	private void m1() {\n" +
+		"		Y<X> s1 = X::new;\n" +
+		"\n" +
+		"		Y<X> s2 = new Y<X>() {\n" +
+		"\n" +
+		"			@Override\n" +
+		"			public X get() {\n" +
+		"				return null;\n" +
+		"			}\n" +
+		"		};\n" +
+		"	}\n" +
+		"}\n");
+SearchPattern pattern = SearchPattern.createPattern(
+		"*",
+		CONSTRUCTOR,
+		METHOD_REFERENCE_EXPRESSION,
+		EXACT_RULE);
+new SearchEngine(this.workingCopies).search(pattern,
+new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()},
+getJavaSearchWorkingCopiesScope(),
+this.resultCollector,
+null);
+assertSearchResults(
+		"src/X.java void X.m1() [X::new] EXACT_MATCH"  
+);	
+}
+
 // Add new tests in JavaSearchBugs8Tests
 }
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
index c3883db..abc8f0c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
@@ -18,8 +18,7 @@
 import java.util.Iterator;
 import java.util.List;
 
-import junit.framework.Test;
-
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.ProjectScope;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.Platform;
@@ -49,6 +48,8 @@
 import org.eclipse.text.edits.TextEdit;
 import org.osgi.service.prefs.BackingStoreException;
 
+import junit.framework.Test;
+
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class ImportRewriteTest extends AbstractJavaModelTests {
 
@@ -107,6 +108,40 @@
 	}
 
 	/**
+	 * Expects that imports can be added for types from an unnamed (default) package, and that such
+	 * imports are not reduced into an on-demand import. Imports of types from an unnamed package
+	 * were legal in versions of Java prior to 1.4.
+	 *
+	 * Addresses https://bugs.eclipse.org/461863 ("addImport creates .ypename for unqualified type
+	 * from default package").
+	 */
+	public void testAddImportsFromUnnamedPackage() throws Exception {
+		ICompilationUnit cu = createCompilationUnit("pack1", "C");
+
+		String[] order = new String[] { "java" };
+
+		ImportRewrite imports = newImportsRewrite(cu, order, 2, 2, false);
+		imports.setUseContextToFilterImplicitImports(true);
+		imports.addImport("java.util.ArrayDeque");
+		imports.addImport("java.util.ArrayList");
+		imports.addImport("Bar");
+		imports.addImport("Foo");
+
+		apply(imports);
+
+		StringBuffer expected = new StringBuffer();
+		expected.append("package pack1;\n");
+		expected.append("\n");
+		expected.append("import java.util.*;\n");
+		expected.append("\n");
+		expected.append("import Bar;\n");
+		expected.append("import Foo;\n");
+		expected.append("\n");
+		expected.append("public class C {}");
+		assertEqualString(cu.getSource(), expected.toString());
+	}
+
+	/**
 	 * Addresses https://bugs.eclipse.org/412929 ("Adding a type results in adding a package and
 	 * later does not honor order").
 	 */
@@ -1411,6 +1446,61 @@
 		assertEqualString(cuWithoutFiltering.getSource(), expectedWithoutFiltering.toString());
 	}
 
+	/**
+	 * Addresses https://bugs.eclipse.org/460484 ("ImportRewrite throws SIOOBE when trying to add
+	 * import").
+	 */
+	public void testAddAdjacentImportWithCommonPrefixButLongerInitialSegment() throws Exception {
+		StringBuffer contents = new StringBuffer();
+		contents.append("package pack1;\n");
+		contents.append("\n");
+		contents.append("import a.FromA;\n");
+		contents.append("import b.FromB;\n");
+		contents.append("\n");
+		contents.append("public class Clazz {}\n");
+		ICompilationUnit cu = createCompilationUnit("pack1", "Clazz", contents.toString());
+
+		ImportRewrite rewrite = newImportsRewrite(cu, new String[] {}, 999, 999, true);
+		rewrite.setUseContextToFilterImplicitImports(true);
+		// Expect that no exception is thrown when "ab" is compared with "a".
+		rewrite.addImport("ab.FromAb");
+		apply(rewrite);
+
+		StringBuffer expected = new StringBuffer();
+		expected.append("package pack1;\n");
+		expected.append("\n");
+		expected.append("import a.FromA;\n");
+		expected.append("import ab.FromAb;\n");
+		expected.append("import b.FromB;\n");
+		expected.append("\n");
+		expected.append("public class Clazz {}\n");
+		assertEqualString(cu.getSource(), expected.toString());
+	}
+	
+	// https://bugs.eclipse.org/459320
+	public void testAddImportToCuNotOnClasspath() throws Exception {
+		StringBuffer contents = new StringBuffer();
+		contents.append("package pack1;\n");
+		contents.append("\n");
+		contents.append("public class Clazz {}\n");
+		
+		createFolder("/P/alt-src/pack1/");
+		IFile clazz = createFile("/P/alt-src/pack1/Clazz.java", contents.toString());
+		ICompilationUnit cu = (ICompilationUnit) JavaCore.create(clazz);
+		cu.becomeWorkingCopy(null);
+		
+		try {
+			ImportRewrite rewrite = newImportsRewrite(cu, new String[] {}, 999, 999, true);
+			rewrite.setUseContextToFilterImplicitImports(true);
+			rewrite.addImport("pack1.AnotherClass");
+			apply(rewrite);
+			
+			assertEqualString(cu.getSource(), contents.toString());
+		} finally {
+			cu.discardWorkingCopy();
+		}
+	}
+
 	public void testAddImports1() throws Exception {
 
 		IPackageFragment pack1= this.sourceFolder.createPackageFragment("pack1", false, null);
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs
index d1fb84b..c02097a 100644
--- a/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs
@@ -54,7 +54,7 @@
 org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
 org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
 org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
 org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
 org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
 org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
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 dffb480..05f3e17 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
@@ -23,6 +23,7 @@
  *								bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
  *								Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
  *								Bug 440687 - [compiler][batch][null] improve command line option for external annotations
+ *								Bug 408815 - [batch][null] Add CLI option for COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS
  *     Jesper S Moller   - Contributions for
  *								bug 407297 - [1.8][compiler] Control generation of parameter names by option
  *    Mat Booth - Contribution for bug 405176 
@@ -3994,6 +3995,11 @@
 			} else if (token.equals("switchDefault")) { //$NON-NLS-1$
 				setSeverity(CompilerOptions.OPTION_ReportMissingDefaultCase, severity, isEnabling);
 				return;
+			} else if (token.equals("syntacticAnalysis")) { //$NON-NLS-1$
+				this.options.put(
+						CompilerOptions.OPTION_SyntacticNullAnalysisForFields,
+						isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+				return;
 			}
 			break;
 		case 't' :
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 275e4e4..217d1b0 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
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2014 IBM Corporation and others.
+# Copyright (c) 2000, 2015 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
 #								bug 374605 - Unreasonable warning for enum-based switch statements
 #								bug 388281 - [compiler][null] inheritance of null annotations as an option
 #								bug 440687 - [compiler][batch][null] improve command line option for external annotations
+#								Bug 408815 - [batch][null] Add CLI option for COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS
 #		Alan Moraes <alan@kelon.org> - Contribution for bug 383644
 #		Jesper S Moller - Contribution for bug 407297 - [1.8][compiler] Control generation of parameter names by option
 ###############################################################################
@@ -26,7 +27,7 @@
 compiler.name = Eclipse Compiler for Java(TM)
 #Format: compiler.version = (The place holders will be automatically filled. Do not remove or alter it)
 compiler.version = bundle_qualifier, bundle_version
-compiler.copyright = Copyright IBM Corp 2000, 2013. All rights reserved.
+compiler.copyright = Copyright IBM Corp 2000, 2015. All rights reserved.
 
 ###{ObjectTeams:
 otdtc.name = Extension for Object Teams
@@ -419,6 +420,7 @@
 \                           errors and warnings\n\
 \      switchDefault      + switch statement lacking a default case\n\
 \      syncOverride         missing synchronized in synchr. method override\n\
+\      syntacticAnalysis    perform syntax-based null analysis for fields\n\
 \      syntheticAccess      synthetic access for innerclass\n\
 \      tasks(<tags separated by |>) tasks identified by tags inside comments\n\
 \      typeHiding         + type parameter hiding another type\n\
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 32caf1f..498026a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -35,6 +35,7 @@
  *								Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
  *								Bug 434483 - [1.8][compiler][inference] Type inference not picked up with method reference
  *								Bug 446442 - [1.8] merge null annotations from super methods
+ *								Bug 437072 - [compiler][null] Null analysis emits possibly incorrect warning for new int[][] despite @NonNullByDefault 
  *     Jesper S Moller - Contributions for
  *								bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
  *								bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
@@ -1115,10 +1116,15 @@
 					scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation);
 				}
 				se8Annotations = Binding.NO_ANNOTATIONS;
+				se8nullBits = 0;
 			}
 			existingType = existingType.withoutToplevelNullAnnotation();
 		}
 		TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
+		if (se8nullBits != 0 && oldLeafType.isBaseType()) {
+			scope.problemReporter().illegalAnnotationForBaseType(typeRef, new Annotation[] { se8NullAnnotation }, se8nullBits);
+			return existingType;
+		}
 		AnnotationBinding [][] goodies = new AnnotationBinding[typeRef.getAnnotatableLevels()][];
 		goodies[0] = se8Annotations;  // @T X.Y.Z local; ==> @T should annotate X
 		TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 0209dee..5eea550 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -840,7 +840,8 @@
 			resolveAnnotations(this.scope, this.annotations, this.binding);
 			
 			long sourceLevel = this.scope.compilerOptions().sourceLevel;
-			validateNullAnnotations(this.scope.environment().usesNullTypeAnnotations());
+			if (sourceLevel < ClassFileConstants.JDK1_8) // otherwise already checked via Argument.createBinding
+				validateNullAnnotations(this.scope.environment().usesNullTypeAnnotations());
 
 			resolveStatements();
 			// check @Deprecated annotation presence
@@ -1017,7 +1018,7 @@
 				this.scope.validateNullAnnotation(this.binding.parameters[i].tagBits, this.arguments[i].type, this.arguments[i].annotations);
 // TODO(stephan) remove once we're sure:
 //					this.binding.parameters[i] = this.binding.parameters[i].unannotated();
-			}			
+			}
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index 1b775ba..035fdf5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -412,8 +412,7 @@
 
 		if (haveDescriptor && !argumentsHaveErrors && blockScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
 			if (!argumentsTypeElided) {
-				AbstractMethodDeclaration.createArgumentBindings(this.arguments, this.binding, this.scope);
-				validateNullAnnotations();
+				AbstractMethodDeclaration.createArgumentBindings(this.arguments, this.binding, this.scope); // includes validation
 				// no application of null-ness default, hence also no warning regarding redundant null annotation
 				mergeParameterNullAnnotations(blockScope);
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
index 57bc2c3..26b6a48 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
@@ -421,32 +421,65 @@
 		return 0; // OK by tagBits
 	}
 
+	static class SearchContradictions extends TypeBindingVisitor {
+		ReferenceBinding typeWithContradiction;
+		@Override
+		public boolean visit(ReferenceBinding referenceBinding) {
+			if ((referenceBinding.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
+				this.typeWithContradiction = referenceBinding;
+				return false;
+			}
+			return true;
+		}
+		@Override
+		public boolean visit(TypeVariableBinding typeVariable) {
+			if (!visit((ReferenceBinding)typeVariable))
+				return false;
+			long allNullBits = typeVariable.tagBits & TagBits.AnnotationNullMASK;
+			if (typeVariable.firstBound != null)
+				allNullBits = typeVariable.firstBound.tagBits & TagBits.AnnotationNullMASK;
+			for (TypeBinding otherBound : typeVariable.otherUpperBounds())
+				allNullBits |= otherBound.tagBits & TagBits.AnnotationNullMASK;
+			if (allNullBits == TagBits.AnnotationNullMASK) {
+				this.typeWithContradiction = typeVariable;
+				return false;
+			}
+			return true;
+		}
+		@Override
+		public boolean visit(RawTypeBinding rawType) {
+			return visit((ReferenceBinding)rawType);
+		}
+		@Override
+		public boolean visit(WildcardBinding wildcardBinding) {
+			long allNullBits = wildcardBinding.tagBits & TagBits.AnnotationNullMASK;
+			switch (wildcardBinding.boundKind) {
+				case Wildcard.EXTENDS:
+					allNullBits |= wildcardBinding.bound.tagBits & TagBits.AnnotationNonNull;
+					break;
+				case Wildcard.SUPER:
+					allNullBits |= wildcardBinding.bound.tagBits & TagBits.AnnotationNullable;
+					break;
+			}
+			if (allNullBits == TagBits.AnnotationNullMASK) {
+				this.typeWithContradiction = wildcardBinding;
+				return false;
+			}
+			return true;
+		}
+		@Override
+		public boolean visit(ParameterizedTypeBinding parameterizedTypeBinding) {
+			if (!visit((ReferenceBinding) parameterizedTypeBinding))
+				return false;
+			return super.visit(parameterizedTypeBinding);
+		}
+	}
+
 	/**
 	 * After a method has substituted type parameters, check if this resulted in any contradictory null annotations.
 	 * Problems are either reported directly (if scope != null) or by returning a ProblemMethodBinding.
 	 */
-	public static MethodBinding checkForContradictions(
-			final MethodBinding method, final Object location, final Scope scope) {
-		
-		class SearchContradictions extends TypeBindingVisitor {
-			ReferenceBinding typeWithContradiction;
-			@Override
-			public boolean visit(ReferenceBinding referenceBinding) {
-				if ((referenceBinding.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
-					this.typeWithContradiction = referenceBinding;
-					return false;
-				}
-				return true;
-			}
-			@Override
-			public boolean visit(TypeVariableBinding typeVariable) {
-				return visit((ReferenceBinding)typeVariable);
-			}
-			@Override
-			public boolean visit(RawTypeBinding rawType) {
-				return visit((ReferenceBinding)rawType);
-			}
-		}
+	public static MethodBinding checkForContradictions(MethodBinding method, Object location, Scope scope) {
 
 		int start = 0, end = 0;
 		if (location instanceof InvocationSite) {
@@ -484,6 +517,12 @@
 		return method;
 	}
 
+	public static boolean hasContradictions(TypeBinding type) {
+		SearchContradictions searchContradiction = new SearchContradictions();
+		TypeBindingVisitor.visit(searchContradiction, type);
+		return searchContradiction.typeWithContradiction != null;
+	}
+
 	public static TypeBinding strongerType(TypeBinding type1, TypeBinding type2, LookupEnvironment environment) {
 		if ((type1.tagBits & TagBits.AnnotationNonNull) != 0)
 			return mergeTypeAnnotations(type1, type2, true, environment);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 8ddad99..a7adb88 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -33,6 +33,7 @@
  *							Bug 441734 - [1.8][inference] Generic method with nested parameterized type argument fails on method reference
  *							Bug 438945 - [1.8] NullPointerException InferenceContext18.checkExpression in java 8 with generics, primitives, and overloading
  *							Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
+ *							Bug 448709 - [1.8][null] ensure we don't infer types that violate null constraints on a type parameter's bound
  *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contribution for
  *                          Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
  *******************************************************************************/
@@ -697,39 +698,41 @@
         	scope.problemReporter().unhandledException(methodExceptions[i], this);
         }
         if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
-        	// TODO: simplify by using this.freeParameters?
-        	int len;
-        	int expectedlen = this.binding.parameters.length;
-        	int providedLen = this.descriptor.parameters.length;
-        	if (this.receiverPrecedesParameters)
-        		providedLen--; // one parameter is 'consumed' as the receiver
-        	boolean isVarArgs = false;
-        	if (this.binding.isVarargs()) {
-        		isVarArgs = (providedLen == expectedlen)
-					? !this.descriptor.parameters[expectedlen-1].isCompatibleWith(this.binding.parameters[expectedlen-1])
-					: true;
-        		len = providedLen; // binding parameters will be padded from InferenceContext18.getParameter()
-        	} else {
-        		len = Math.min(expectedlen, providedLen);
-        	}
-    		for (int i = 0; i < len; i++) {
-    			TypeBinding descriptorParameter = this.descriptor.parameters[i + (this.receiverPrecedesParameters ? 1 : 0)];
-    			TypeBinding bindingParameter = InferenceContext18.getParameter(this.binding.parameters, i, isVarArgs);
-    			NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(bindingParameter, descriptorParameter, FlowInfo.UNKNOWN);
-    			if (annotationStatus.isAnyMismatch()) {
-    				// immediate reporting:
-    				scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, bindingParameter, descriptorParameter, this.descriptor, i, annotationStatus);
-    			}
-    		}
-        	if (!this.binding.isConstructor() && (this.descriptor.returnType.tagBits & TagBits.AnnotationNonNull) != 0) {
-        		// since constructors never return null we don't have to check those anyway.
-        		if ((this.binding.returnType.tagBits & TagBits.AnnotationNonNull) == 0) {
-        			char[][] providedAnnotationName = ((this.binding.returnType.tagBits & TagBits.AnnotationNullable) != 0) ?
-        					scope.environment().getNullableAnnotationName() : null;
-        			scope.problemReporter().illegalReturnRedefinition(this, this.descriptor,
-        					scope.environment().getNonNullAnnotationName(),
-        					providedAnnotationName, this.binding.returnType);
-        		}
+        	if (this.expectedType == null || !NullAnnotationMatching.hasContradictions(this.expectedType)) { // otherwise assume it has been reported and we can do nothing here
+	        	// TODO: simplify by using this.freeParameters?
+	        	int len;
+	        	int expectedlen = this.binding.parameters.length;
+	        	int providedLen = this.descriptor.parameters.length;
+	        	if (this.receiverPrecedesParameters)
+	        		providedLen--; // one parameter is 'consumed' as the receiver
+	        	boolean isVarArgs = false;
+	        	if (this.binding.isVarargs()) {
+	        		isVarArgs = (providedLen == expectedlen)
+						? !this.descriptor.parameters[expectedlen-1].isCompatibleWith(this.binding.parameters[expectedlen-1])
+						: true;
+	        		len = providedLen; // binding parameters will be padded from InferenceContext18.getParameter()
+	        	} else {
+	        		len = Math.min(expectedlen, providedLen);
+	        	}
+	    		for (int i = 0; i < len; i++) {
+	    			TypeBinding descriptorParameter = this.descriptor.parameters[i + (this.receiverPrecedesParameters ? 1 : 0)];
+	    			TypeBinding bindingParameter = InferenceContext18.getParameter(this.binding.parameters, i, isVarArgs);
+	    			NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(bindingParameter, descriptorParameter, FlowInfo.UNKNOWN);
+	    			if (annotationStatus.isAnyMismatch()) {
+	    				// immediate reporting:
+	    				scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, bindingParameter, descriptorParameter, this.descriptor, i, annotationStatus);
+	    			}
+	    		}
+	        	if (!this.binding.isConstructor() && (this.descriptor.returnType.tagBits & TagBits.AnnotationNonNull) != 0) {
+	        		// since constructors never return null we don't have to check those anyway.
+	        		if ((this.binding.returnType.tagBits & TagBits.AnnotationNonNull) == 0) {
+	        			char[][] providedAnnotationName = ((this.binding.returnType.tagBits & TagBits.AnnotationNullable) != 0) ?
+	        					scope.environment().getNullableAnnotationName() : null;
+	        			scope.problemReporter().illegalReturnRedefinition(this, this.descriptor,
+	        					scope.environment().getNonNullAnnotationName(),
+	        					providedAnnotationName, this.binding.returnType);
+	        		}
+	        	}
         	}
         }
         this.freeParameters = null; // not used after method lookup
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index c0391b6..c146eff 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,7 @@
  *								Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
  *								Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E"
  *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
+ *								Bug 437072 - [compiler][null] Null analysis emits possibly incorrect warning for new int[][] despite @NonNullByDefault 
  *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
  *                          Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
  *                          Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
@@ -842,6 +843,8 @@
 				scope.problemReporter().nullityMismatchTypeArgument(variable, this.resolvedType, this);
     	}
 	}
+	if (this.resolvedType.leafComponentType().isBaseType() && hasNullTypeAnnotation())
+		scope.problemReporter().illegalAnnotationForBaseType(this, this.annotations[0], this.resolvedType.tagBits & TagBits.AnnotationNullMASK);
 }
 /** Retrieve the null annotation that has been translated to the given nullTagBits. */
 public Annotation findAnnotation(long nullTagBits) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
index bc64451..6b61bcf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
@@ -10,9 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.classfmt;
 
-import static org.eclipse.jdt.core.util.ExternalAnnotationUtil.NONNULL;
-import static org.eclipse.jdt.core.util.ExternalAnnotationUtil.NULLABLE;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -35,6 +32,18 @@
 	public static final String CLASS_PREFIX = "class "; //$NON-NLS-1$
 	public static final String SUPER_PREFIX = "super "; //$NON-NLS-1$
 
+	/** Representation of a 'nullable' annotation, independent of the concrete annotation name used in Java sources. */
+	public static final char NULLABLE = '0';
+
+	/** Representation of a 'nonnull' annotation, independent of the concrete annotation name used in Java sources. */
+	public static final char NONNULL = '1';
+
+	/**
+	 * Represents absence of a null annotation. Useful for removing an existing null annotation.
+	 * This character is used only internally, it is not part of the Eclipse External Annotation file format.
+	 */
+	public static final char NO_ANNOTATION = '@';
+
 	static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
 
 	private static final String TYPE_PARAMETER_PREFIX = " <"; //$NON-NLS-1$
@@ -60,15 +69,9 @@
 	private void initialize(InputStream input) throws IOException {
 		LineNumberReader reader = new LineNumberReader(new InputStreamReader(input));
 		try {
-			String line = reader.readLine().trim();
-			if (line.startsWith(CLASS_PREFIX)) {
-				line = line.substring(CLASS_PREFIX.length());
-			} else {
-				throw new IOException("missing class header in annotation file"); //$NON-NLS-1$
-			}
-			if (!trimTail(line).equals(this.typeName)) {
-				throw new IOException("mismatching class name in annotation file, expected "+this.typeName+", but header said "+line); //$NON-NLS-1$ //$NON-NLS-2$
-			}
+			assertClassHeader(reader.readLine(), this.typeName);
+
+			String line;
 			if ((line = reader.readLine()) == null) {
 				return;
 			}
@@ -81,7 +84,9 @@
 						return;
 				} 
 			}
+			String pendingLine;
 			do {
+				pendingLine = null;
 				line = line.trim();
 				if (line.isEmpty()) continue;
 				String rawSig = null, annotSig = null;
@@ -102,8 +107,11 @@
 					line = reader.readLine();
 					if (line == null || line.isEmpty())
 						continue; // skip since optional line with annotations is missing
-					if (line.charAt(0) == ' ')
-						annotSig = line.substring(1);
+					if (line.charAt(0) != ' ') {
+						pendingLine = line; // push back what appears to be the next selector, not a signature
+						continue;
+					}
+					annotSig = line.substring(1);
 				} catch (Exception ex) {
 					// continue to escalate below
 				}
@@ -126,14 +134,38 @@
 						this.fieldAnnotationSources = new HashMap<String, String>();
 					this.fieldAnnotationSources.put(selector+':'+rawSig, annotSig);
 				}
-			} while ((line = reader.readLine()) != null);
+			} while (((line = pendingLine) != null) || (line = reader.readLine()) != null);
 		} finally {
 			reader.close();
 		}
 	}
 
+	/**
+	 * Assert that the given line is a class header for 'typeName' (slash-separated qualified name).
+	 */
+	public static void assertClassHeader(String line, String typeName) throws IOException {
+		if (line.startsWith(CLASS_PREFIX)) {
+			line = line.substring(CLASS_PREFIX.length());
+		} else {
+			throw new IOException("missing class header in annotation file"); //$NON-NLS-1$
+		}
+		if (!trimTail(line).equals(typeName)) {
+			throw new IOException("mismatching class name in annotation file, expected "+typeName+", but header said "+line); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	/**
+	 * Extract the signature from a line of an external annotation file.
+	 * Answers null if line is not in the expected format.
+	 */
+	public static String extractSignature(String line) {
+		if (line == null || line.isEmpty() || line.charAt(0) != ' ')
+			return null;
+		return trimTail(line.substring(1));
+	}
+
 	/** Lines may contain arbitrary trailing data, separated by white space. */
-	protected String trimTail(String line) {
+	protected static String trimTail(String line) {
 		int tail = line.indexOf(' ');
 		if (tail == -1)
 			tail = line.indexOf('\t');
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index d4d99fd..c6dcc0a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,6 +20,7 @@
  *								Bug 453483 - [compiler][null][loop] Improve null analysis for loops
  *								Bug 455723 - Nonnull argument not correctly inferred in loop
  *								Bug 415790 - [compiler][resource]Incorrect potential resource leak warning in for loop with close in try/catch
+ *								Bug 446691 - [1.8][null][compiler] NullPointerException in SingleNameReference.analyseCode
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
@@ -510,7 +511,7 @@
 			current = initializationContext.initializationParent;
 		} else if (current instanceof ExceptionHandlingFlowContext) {
 			ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current;
-			current = exceptionContext.initializationParent == null ? exceptionContext.getLocalParent() : exceptionContext.initializationParent;
+			current = exceptionContext.initializationParent == null ? exceptionContext.parent : exceptionContext.initializationParent;
 		} else {
 			current = current.getLocalParent();
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
index 2b1e8b9..68770ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
@@ -317,7 +317,7 @@
 		for (int i = 0; i < length; i++) {
 			TypeVariableBinding typeParameter = typeParameters[i];
 			InferenceVariable variable = variables[i];
-			TypeBound[] someBounds = typeParameter.getTypeBounds(variable, new InferenceSubstitution(context.environment, context.inferenceVariables));
+			TypeBound[] someBounds = typeParameter.getTypeBounds(variable, new InferenceSubstitution(context));
 			boolean hasProperBound = false;
 			if (someBounds.length > 0)
 				hasProperBound = addBounds(someBounds, context.environment);
@@ -610,7 +610,7 @@
 			// construct theta = [P1:=alpha1,...]
 			final InferenceVariable[] alphas = new InferenceVariable[gAlpha.arguments.length];
 			System.arraycopy(gAlpha.arguments, 0, alphas, 0, alphas.length);
-			InferenceSubstitution theta = new InferenceSubstitution(context.environment, alphas) {
+			InferenceSubstitution theta = new InferenceSubstitution(context.environment, alphas, context.currentInvocation) {
 				@Override
 				protected TypeBinding getP(int i) {
 					return parameters[i];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
index be2c03d..c9a37dc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
@@ -240,7 +240,7 @@
 	 * Substitute any type variables mentioned in 'type' by the corresponding inference variable, if one exists. 
 	 */
 	public TypeBinding substitute(TypeBinding type) {
-		InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this.environment, this.inferenceVariables);
+		InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this);
 		return 	inferenceSubstitution.substitute(inferenceSubstitution, type);
 	}
 
@@ -392,7 +392,7 @@
 			}
 			// 4. bullet: assemble C:
 			Set<ConstraintFormula> c = new HashSet<ConstraintFormula>();
-			if (!addConstraintsToC(this.invocationArguments, c, method, this.inferenceKind, false))
+			if (!addConstraintsToC(this.invocationArguments, c, method, this.inferenceKind, false, invocationSite))
 				return null;
 			// 5. bullet: determine B4 from C
 			while (!c.isEmpty()) {
@@ -444,7 +444,9 @@
 		}
 	}
 
-	private boolean addConstraintsToC(Expression[] exprs, Set<ConstraintFormula> c, MethodBinding method, int inferenceKindForMethod, boolean interleaved) throws InferenceFailureException {
+	private boolean addConstraintsToC(Expression[] exprs, Set<ConstraintFormula> c, MethodBinding method, int inferenceKindForMethod, boolean interleaved, InvocationSite site)
+			throws InferenceFailureException
+	{
 		TypeBinding[] fs;
 		if (exprs != null) {
 			int k = exprs.length;
@@ -464,7 +466,8 @@
 			}
 			for (int i = 0; i < k; i++) {
 				TypeBinding fsi = fs[Math.min(i, p-1)];
-				TypeBinding substF = substitute(fsi);
+				InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this.environment, this.inferenceVariables, site);
+				TypeBinding substF = inferenceSubstitution.substitute(inferenceSubstitution,fsi);
 				if (!addConstraintsToC_OneExpr(exprs[i], c, fsi, substF, method, interleaved))
 					return false;
 	        }
@@ -472,8 +475,9 @@
 		return true;
 	}
 
-	private boolean addConstraintsToC_OneExpr(Expression expri, Set<ConstraintFormula> c, TypeBinding fsi, TypeBinding substF, MethodBinding method, boolean interleaved) throws InferenceFailureException {
-		
+	private boolean addConstraintsToC_OneExpr(Expression expri, Set<ConstraintFormula> c, TypeBinding fsi, TypeBinding substF, MethodBinding method, boolean interleaved)
+			throws InferenceFailureException
+	{	
 		// For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
 		if (!expri.isPertinentToApplicability(fsi, method)) {
 			c.add(new ConstraintExpressionFormula(expri, substF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT));
@@ -536,7 +540,7 @@
 					resumeSuspendedInference(prevInvocation);
 				}
 			}
-			return addConstraintsToC(arguments, c, innerMethod.genericMethod(), applicabilityKind, interleaved);
+			return addConstraintsToC(arguments, c, innerMethod.genericMethod(), applicabilityKind, interleaved, invocation);
 		} else if (expri instanceof ConditionalExpression) {
 			ConditionalExpression ce = (ConditionalExpression) expri;
 			return addConstraintsToC_OneExpr(ce.valueIfTrue, c, fsi, substF, method, interleaved)
@@ -1623,4 +1627,4 @@
 			}
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
index 1214f5d..c76e3ba 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
@@ -19,12 +19,18 @@
 
 	private LookupEnvironment environment;
 	private InferenceVariable[] variables;
+	private InvocationSite site;
 
-	public InferenceSubstitution(LookupEnvironment environment, InferenceVariable[] variables) {
+	public InferenceSubstitution(LookupEnvironment environment, InferenceVariable[] variables, InvocationSite site) {
 		this.environment = environment;
 		this.variables = variables;
+		this.site = site;
 	}
-	
+
+	public InferenceSubstitution(InferenceContext18 context) {
+		this(context.environment, context.inferenceVariables, context.currentInvocation);
+	}
+
 	/**
 	 * Override method {@link Scope.Substitutor#substitute(Substitution, TypeBinding)}, 
 	 * to add substitution of types other than type variables.
@@ -32,7 +38,7 @@
 	public TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
 		for (int i = 0; i < this.variables.length; i++) {
 			InferenceVariable variable = this.variables[i];
-			if (TypeBinding.equalsEquals(getP(i), originalType)) {
+			if (this.site == variable.site && TypeBinding.equalsEquals(getP(i), originalType)) {
 				if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && originalType.hasNullTypeAnnotations())
 					return this.environment.createAnnotatedType(variable.withoutToplevelNullAnnotation(), originalType.getTypeAnnotations());
 				return variable;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index d28535f..96f24e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -125,6 +125,35 @@
 				methodSubstitute = methodSubstitute.inferFromExpectedType(scope, inferenceContext);
 				if (methodSubstitute == null)
 					return null;
+			} else if (compilerOptions.sourceLevel == ClassFileConstants.JDK1_7) {
+				// bug 425203 - consider additional constraints to conform to buggy javac behavior
+				if (methodSubstitute.returnType != TypeBinding.VOID) {
+					TypeBinding expectedType = invocationSite.invocationTargetType();
+					// In case of a method like <T> List<T> foo(T arg), solution based on return type
+					// should not be preferred vs solution based on parameter types, so do not attempt
+					// to use return type based inference in this case
+ 					if (expectedType != null && !originalMethod.returnType.mentionsAny(originalMethod.parameters, -1)) {
+						TypeBinding uncaptured = methodSubstitute.returnType.uncapture(scope);
+						if (!methodSubstitute.returnType.isCompatibleWith(expectedType) &&
+								expectedType.isCompatibleWith(uncaptured)) { 
+							InferenceContext oldContext = inferenceContext;
+							inferenceContext = new InferenceContext(originalMethod);
+							// Include additional constraint pertaining to the expected type
+							originalMethod.returnType.collectSubstitutes(scope, expectedType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
+							ParameterizedGenericMethodBinding substitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext);
+							if (substitute != null && substitute.returnType.isCompatibleWith(expectedType)) {
+								// Do not use the new solution if it results in incompatibilities in parameter types
+								if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) {
+									methodSubstitute = substitute;
+								} else {
+									inferenceContext = oldContext;
+								}
+							} else {
+								inferenceContext = oldContext;
+							}
+						}
+					}					
+				}
 			}
 		}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 740687d..032efd5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -50,6 +50,8 @@
  *								Bug 452194 - Code no longer compiles in 4.4.1, but with confusing error
  *								Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
  *								Bug 456236 - [1.8][null] Cannot infer type when constructor argument is annotated with @Nullable
+ *								Bug 437072 - [compiler][null] Null analysis emits possibly incorrect warning for new int[][] despite @NonNullByDefault
+ *								Bug 462083 - [1.8][inference] Java 8 generic return type mismatch with interface involving type parameter.
  *     Jesper S Moller - Contributions for
  *								Bug 378674 - "The method can be declared as static" is wrong
  *  							Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
@@ -620,7 +622,15 @@
 				        }
 			        } 
 					break;
-	
+
+				case Binding.INTERSECTION_TYPE18:
+					IntersectionTypeBinding18 intersection = (IntersectionTypeBinding18) originalType;
+					ReferenceBinding[] types = intersection.getIntersectingTypes();
+					TypeBinding[] substitutes = substitute(substitution, types);
+					ReferenceBinding[] refSubsts = new ReferenceBinding[substitutes.length];
+					System.arraycopy(substitutes, 0, refSubsts, 0, substitutes.length);
+					return substitution.environment().createIntersectionType18(refSubsts);
+
 				case Binding.TYPE:
 					if (!originalType.isMemberType()) break;
 					ReferenceBinding originalReferenceType = (ReferenceBinding) originalType;
@@ -1319,7 +1329,7 @@
 			// in >= 1.5 mode, ensure the exactMatch did not match raw types
 			if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5)
 				for (int i = argumentTypes.length; --i >= 0;)
-					if (isPossibleSubtypeOfRawType(argumentTypes[i]))
+					if (isSubtypeOfRawType(argumentTypes[i]))
 						return null;
 			// must find both methods for this case: <S extends A> void foo() {}  and  <N extends B> N foo() { return null; }
 			// or find an inherited method when the exact match is to a bridge method
@@ -3090,7 +3100,8 @@
 
 			// retrieve an exact visible match (if possible)
 			MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
-			if (methodBinding != null) return methodBinding;
+			if (methodBinding != null && methodBinding.isValidBinding())
+				return methodBinding;
 
 			methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite, false);
 //{ObjectTeams: callout to private role method goes through the role class-part:
@@ -4021,7 +4032,7 @@
 		return false;
 	}
 
-	public boolean isPossibleSubtypeOfRawType(TypeBinding paramType) {
+	public boolean isSubtypeOfRawType(TypeBinding paramType) {
 		TypeBinding t = paramType.leafComponentType();
 		if (t.isBaseType()) return false;
 
@@ -4030,7 +4041,6 @@
 		int nextPosition = 0;
 		do {
 			if (currentType.isRawType()) return true;
-			if (!currentType.isHierarchyConnected()) return true; // do not fault in super types right now, so assume one is a raw type
 	
 			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
 			if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
@@ -5496,12 +5506,23 @@
 	}
 
 	public boolean validateNullAnnotation(long tagBits, TypeReference typeRef, Annotation[] annotations) {
-		long nullAnnotationTagBit = tagBits & (TagBits.AnnotationNullMASK);
+		if (typeRef == null)
+			return true;
+		TypeBinding type = typeRef.resolvedType;
+
+		boolean usesNullTypeAnnotations = this.environment().usesNullTypeAnnotations();
+		long nullAnnotationTagBit;
+		if (usesNullTypeAnnotations) {
+			type = type.leafComponentType(); // if it's an array, the annotation applies to the leaf component type
+			nullAnnotationTagBit = type.tagBits & TagBits.AnnotationNullMASK;
+		} else {
+			nullAnnotationTagBit = tagBits & (TagBits.AnnotationNullMASK);
+		}
+		
 		if (nullAnnotationTagBit != 0) {
-			TypeBinding type = typeRef.resolvedType;
 			if (type != null && type.isBaseType()) {
 				// type annotations are *always* illegal for 'void' (already reported)
-				if (!(typeRef.resolvedType.id == TypeIds.T_void && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8))
+				if (!(typeRef.resolvedType.id == TypeIds.T_void && usesNullTypeAnnotations))
 					problemReporter().illegalAnnotationForBaseType(typeRef, annotations, nullAnnotationTagBit);
 				return false;
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
index 19514c0..7e61a2d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
@@ -13,6 +13,7 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 
 public class SignatureWrapper {
 	public char[] signature;
@@ -20,6 +21,7 @@
 	public int end;
 	public int bracket;
 	private boolean use15specifics;
+	private boolean useExternalAnnotations;
 
 	public SignatureWrapper(char[] signature, boolean use15specifics) {
 		this.signature = signature;
@@ -27,6 +29,13 @@
 		this.end = this.bracket = -1;
 		this.use15specifics = use15specifics;
 	}
+	public SignatureWrapper(char[] signature, boolean use15specifics, boolean useExternalAnnotations) {
+		this.signature = signature;
+		this.start = 0;
+		this.end = this.bracket = -1;
+		this.use15specifics = use15specifics;
+		this.useExternalAnnotations = useExternalAnnotations;
+	}
 	public SignatureWrapper(char [] signature) {
 		this(signature, true);
 	}
@@ -35,8 +44,27 @@
 	}
 	public int computeEnd() {
 		int index = this.start;
-		while (this.signature[index] == '[')
-			index++;
+		if (this.useExternalAnnotations) {
+			// in addition to '[' tokens accept null annotations after the first '['
+			skipDimensions: while(true) {
+				switch (this.signature[index]) {
+					case ExternalAnnotationProvider.NONNULL :
+					case ExternalAnnotationProvider.NULLABLE :
+					case ExternalAnnotationProvider.NO_ANNOTATION :
+						if (index == this.start)
+							break skipDimensions;
+						//$FALL-THROUGH$
+					case '[':
+						index++;
+						break;
+					default:
+						break skipDimensions;
+				}
+			}
+		} else {
+			while (this.signature[index] == '[')
+				index++;
+		}
 		switch (this.signature[index]) {
 			case 'L' :
 			case 'T' :
@@ -50,7 +78,7 @@
 					this.end = this.signature.length + 1;
 				break;
 			default :
-				this.end = this.start;
+				this.end = index;
 		}
 
 		if (this.use15specifics || this.end != this.bracket) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index b866bfa..c108d8b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -38,6 +38,7 @@
  *								Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
  *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
  *								Bug 457210 - [1.8][compiler][null] Wrong Nullness errors given on full build build but not on incremental build?
+ *								Bug 461250 - ArrayIndexOutOfBoundsException in SourceTypeBinding.fields
  *      Jesper S Moller <jesper@selskabet.org> -  Contributions for
  *								Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
  *      Till Brychcy - Contributions for
@@ -1167,6 +1168,8 @@
 	ReferenceBinding enclosingType = enclosingType();
 	if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated())
 		this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+	fields();
+	methods();
 
 //{ObjectTeams: do not cache memberTypes.length!
 // During faultInTypesForFieldsAndMethods(), memberTypes may be added (role files, on demand)
@@ -1178,8 +1181,6 @@
 		if (!this.memberTypes[i].isBinaryBinding()) // roles could be binary contained in source
 //carp}
 		((SourceTypeBinding) this.memberTypes[i]).faultInTypesForFieldsAndMethods();
-	fields();
-	methods();
 }
 // NOTE: the type of each field of a source type is resolved when needed
 public FieldBinding[] fields() {
@@ -1204,32 +1205,28 @@
 				ReferenceBinding.sortFields(this.fields, 0, length);
 			this.tagBits |= TagBits.AreFieldsSorted;
 		}
-//{ObjectTeams: don't cache length, may shrink in re-entrant executions
-/*orig
-		for (int i = 0, length = this.fields.length; i < length; i++) {
- */
-		for (int i = 0; i < this.fields.length; i++) {
-// check discouraged field in @Instantation(ALWAYS) roles:
+		FieldBinding[] fieldsSnapshot = this.fields;
+		for (int i = 0, length = fieldsSnapshot.length; i < length; i++) {
+//{ObjectTeams: check discouraged field in @Instantation(ALWAYS) roles:
 		  if (   this.scope != null 
 			  && (this.tagBits & TagBits.AnnotationInstantiation) != 0 
-			  && !this.fields[i].isStatic())
-			  this.scope.problemReporter().fieldInRoleWithInstantiationPolicy(this, this.fields[i]);
+			  && !fieldsSnapshot[i].isStatic())
+			  this.scope.problemReporter().fieldInRoleWithInstantiationPolicy(this, fieldsSnapshot[i]);
 			  
 // after compilation is finished we have no scope, can't resolve any better
 //   		    resolveTypeFor would NPE!
-		  int length = this.fields.length;
 		  if (   this.model!=null
 			  && this.model.getState() == ITranslationStates.STATE_FINAL
-			  && this.fields[i].type == null)
+			  && fieldsSnapshot[i].type == null)
 		  {
-			  this.fields[i] = null;
+			  fieldsSnapshot[i] = null;
 			  failed++;
 		  } else
 //SH}
-			if (resolveTypeFor(this.fields[i]) == null) {
+			if (resolveTypeFor(fieldsSnapshot[i]) == null) {
 				// do not alter original field array until resolution is over, due to reentrance (143259)
-				if (resolvedFields == this.fields) {
-					System.arraycopy(this.fields, 0, resolvedFields = new FieldBinding[length], 0, length);
+				if (resolvedFields == fieldsSnapshot) {
+					System.arraycopy(fieldsSnapshot, 0, resolvedFields = new FieldBinding[length], 0, length);
 				}
 				resolvedFields[i] = null;
 				failed++;
@@ -2697,12 +2694,9 @@
 			if (nullTagBits != 0) {
 				TypeReference returnTypeRef = ((MethodDeclaration)methodDecl).returnType;
 				if (this.scope.environment().usesNullTypeAnnotations()) {
-					if (nullTagBits != (method.returnType.tagBits & TagBits.AnnotationNullMASK)) {
-						if (!this.scope.validateNullAnnotation(nullTagBits, returnTypeRef, methodDecl.annotations)) {
-							method.returnType.tagBits &= ~TagBits.AnnotationNullMASK;
-						}
-						method.tagBits &= ~TagBits.AnnotationNullMASK;
-					}
+					if (!this.scope.validateNullAnnotation(nullTagBits, returnTypeRef, methodDecl.annotations))
+						method.returnType.tagBits &= ~TagBits.AnnotationNullMASK;
+					method.tagBits &= ~TagBits.AnnotationNullMASK;
 				} else {
 					if (!this.scope.validateNullAnnotation(nullTagBits, returnTypeRef, methodDecl.annotations))
 						method.tagBits &= ~TagBits.AnnotationNullMASK;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
index 13a6dfc..d39a3be 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -316,8 +316,19 @@
 				initializer.bodyEnd = initializer.bodyStart;
 			}
 		} else {
-			initializer.declarationSourceEnd = braceEnd;
-			initializer.bodyEnd  = braceStart - 1;
+			if (braceEnd < initializer.declarationSourceStart) {
+				initializer.declarationSourceEnd = initializer.declarationSourceStart;
+				initializer.bodyEnd  = initializer.declarationSourceEnd;
+			} else {
+				initializer.declarationSourceEnd = braceEnd;
+				initializer.bodyEnd  = braceStart - 1;
+			}
+			if (initializer.bodyStart > initializer.declarationSourceEnd) {
+				initializer.bodyStart = initializer.declarationSourceEnd;
+				if(initializer.block != null) {
+					initializer.block.sourceStart = initializer.declarationSourceStart;
+				}
+			}
 		}
 		if(initializer.block != null) {
 			initializer.block.sourceEnd = initializer.declarationSourceEnd;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 428b453..151d5da 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -27,6 +27,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -718,7 +719,7 @@
 	}
 	/**
 	 * Returns the contents of the given zip entry as a byte array.
-	 * @throws IOException if a problem occured reading the zip entry.
+	 * @throws IOException if a problem occurred reading the zip entry.
 	 */
 	public static byte[] getZipEntryByteContent(ZipEntry ze, ZipFile zip)
 		throws IOException {
@@ -1132,6 +1133,15 @@
 	}
 
 	public static void collectRunningVMBootclasspath(List bootclasspaths) {
+		for (String filePath : collectFilesNames()) {
+			FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null);
+			if (currentClasspath != null) {
+				bootclasspaths.add(currentClasspath);
+			}
+		}
+	}
+
+	public static List<String> collectFilesNames() {
 		/* no bootclasspath specified
 		 * we can try to retrieve the default librairies of the VM used to run
 		 * the batch compiler
@@ -1154,15 +1164,11 @@
 				bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
 			}
 		}
+		List<String> filePaths = new ArrayList<>();
 		if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) {
 			StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator);
-			String token;
 			while (tokenizer.hasMoreTokens()) {
-				token = tokenizer.nextToken();
-				FileSystem.Classpath currentClasspath = FileSystem.getClasspath(token, null, null);
-				if (currentClasspath != null) {
-					bootclasspaths.add(currentClasspath);
-				}
+				filePaths.add(tokenizer.nextToken());
 			}
 		} else {
 			// try to get all jars inside the lib folder of the java home
@@ -1185,18 +1191,14 @@
 						File[] current = systemLibrariesJars[i];
 						if (current != null) {
 							for (int j = 0, max2 = current.length; j < max2; j++) {
-								FileSystem.Classpath classpath =
-									FileSystem.getClasspath(current[j].getAbsolutePath(),
-										null, false, null, null);
-								if (classpath != null) {
-									bootclasspaths.add(classpath);
-								}
+								filePaths.add(current[j].getAbsolutePath());
 							}
 						}
 					}
 				}
 			}
 		}
+		return filePaths;
 	}
 	public static int getParameterCount(char[] methodSignature) {
 		try {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportName.java
index 34d6bc9..6ce9e75 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportName.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportName.java
@@ -49,12 +49,12 @@
 /* orig:
 	public static ImportName createFor(boolean isStatic, String qualifiedName) {
 		String containerName = Signature.getQualifier(qualifiedName);
-		String simpleName = qualifiedName.substring(containerName.length() + 1);
+		String simpleName = Signature.getSimpleName(qualifiedName);
 		return new ImportName(isStatic, containerName, simpleName);
   :giro */
 	public static ImportName createFor(boolean isStatic, /*OT:*/boolean isBase, String qualifiedName) {
 		String containerName = Signature.getQualifier(qualifiedName);
-		String simpleName = qualifiedName.substring(containerName.length() + 1);
+		String simpleName = Signature.getSimpleName(qualifiedName);
 		return new ImportName(isStatic, /*OT:*/isBase, containerName, simpleName);
 // SH}
 	}
@@ -76,7 +76,7 @@
 		this.containerName = containerName;
 		this.simpleName = simpleName;
 
-		this.qualifiedName = this.containerName + "." + this.simpleName; //$NON-NLS-1$;
+		this.qualifiedName = containerName.isEmpty() ? simpleName : containerName + "." + simpleName; //$NON-NLS-1$;
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportRewriteConfiguration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportRewriteConfiguration.java
index c77fee8..2055df1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportRewriteConfiguration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/ImportRewriteConfiguration.java
@@ -18,6 +18,9 @@
 import java.util.Set;
 
 import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageDeclaration;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.JavaProject;
 
 /**
@@ -159,7 +162,25 @@
 
 				implicitImportContainerNames.add("java.lang"); //$NON-NLS-1$
 
-				String compilationUnitPackageName = compilationUnit.getParent().getElementName();
+				IJavaElement packageFragment = compilationUnit.getParent();
+				String compilationUnitPackageName = packageFragment.getElementName();
+				if (compilationUnitPackageName.isEmpty() && !packageFragment.exists() && compilationUnit.exists()) {
+					/*
+					 * For a file outside of the build path, JavaCore#create(IFile) creates an
+					 * ICompilationUnit with the file's parent folder as package fragment root, and a default package.
+					 * That "wrong" package is problematic for the ImportRewrite, since it doesn't get filtered
+					 * and eventually leads to unused import statements.
+					 */
+					try {
+						IPackageDeclaration[] packageDeclarations = compilationUnit.getPackageDeclarations();
+						if (packageDeclarations.length > 0) {
+							implicitImportContainerNames.add(packageDeclarations[0].getElementName());
+							return implicitImportContainerNames;
+						}
+					} catch (JavaModelException e) {
+						// continue
+					}
+				}
 				implicitImportContainerNames.add(compilationUnitPackageName);
 
 				return implicitImportContainerNames;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/OnDemandComputer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/OnDemandComputer.java
index c180b35..069fc0f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/OnDemandComputer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/imports/OnDemandComputer.java
@@ -59,15 +59,18 @@
 //{ObjectTeams: no on-demand base imports
 			if (containerOnDemand.isBase) continue;
 // SH}
-			Collection<ImportName> containerImports = containerAndImports.getValue();
+			// Imports from an unnamed package should not be reduced (see bug 461863).
+			boolean isUnnamedPackage = containerOnDemand.containerName.isEmpty();
 
-			Set<String> explicitSimpleNames =
-					containerOnDemand.isStatic ? staticExplicitSimpleNames : typeExplicitSimpleNames;
+			if (touchedContainers.contains(containerOnDemand) && !isUnnamedPackage) {
+				Collection<ImportName> containerImports = containerAndImports.getValue();
 
-			int onDemandThreshold =
-					containerOnDemand.isStatic ? this.staticOnDemandThreshold : this.typeOnDemandThreshold;
+				Set<String> explicitSimpleNames =
+						containerOnDemand.isStatic ? staticExplicitSimpleNames : typeExplicitSimpleNames;
 
-			if (touchedContainers.contains(containerOnDemand)) {
+				int onDemandThreshold =
+						containerOnDemand.isStatic ? this.staticOnDemandThreshold : this.typeOnDemandThreshold;
+
 				OnDemandReduction candidate = maybeReduce(
 						containerOnDemand, containerImports, onDemandThreshold, explicitSimpleNames);
 				if (candidate != null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
index 2e3eea4..a24a91a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
@@ -37,6 +37,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 import org.eclipse.jdt.internal.compiler.lookup.SignatureWrapper;
 import org.eclipse.jdt.internal.core.ClasspathEntry;
+import org.eclipse.jdt.internal.core.util.KeyToSignature;
 
 /**
  * Utilities for accessing and manipulating text files that externally define annotations for a given Java type.
@@ -48,16 +49,16 @@
 public final class ExternalAnnotationUtil {
 
 	/** Representation of a 'nullable' annotation, independent of the concrete annotation name used in Java sources. */
-	public static final char NULLABLE = '0';
+	public static final char NULLABLE = ExternalAnnotationProvider.NULLABLE;
 
 	/** Representation of a 'nonnull' annotation, independent of the concrete annotation name used in Java sources. */
-	public static final char NONNULL = '1';
+	public static final char NONNULL = ExternalAnnotationProvider.NONNULL;
 
 	/**
 	 * Represents absence of a null annotation. Useful for removing an existing null annotation.
 	 * This character is used only internally, it is not part of the Eclipse External Annotation file format.
 	 */
-	public static final char NO_ANNOTATION = '@';
+	public static final char NO_ANNOTATION = ExternalAnnotationProvider.NO_ANNOTATION;
 
 	/** Strategy for merging a new signature with an existing (possibly annotated) signature. */
 	public static enum MergeStrategy {
@@ -78,12 +79,21 @@
 	 * @return a signature in class file format
 	 */
 	public static String extractGenericSignature(IMethodBinding methodBinding) {
-		// Note that IMethodBinding.binding is not accessible, hence we need to reverse engineer from the key:
-		
-		// method key contains the signature between '(' and '|': "class.selector(params)return|throws"
-		int open= methodBinding.getKey().indexOf('(');
-		int throwStart= methodBinding.getKey().indexOf('|');
-		return throwStart == -1 ? methodBinding.getKey().substring(open) : methodBinding.getKey().substring(open, throwStart);
+		// Note that IMethodBinding.binding is not accessible, hence we need to recover the signature from the key:
+		KeyToSignature parser = new KeyToSignature(methodBinding.getKey(), KeyToSignature.SIGNATURE, true);
+		parser.parse();
+		return parser.toString();
+	}
+
+	/**
+	 * Answer the given types's signature in class file format.
+	 * @param type binding representing a type
+	 * @return a signature in class file format
+	 */
+	public static String extractGenericTypeSignature(ITypeBinding type) {
+		KeyToSignature parser = new KeyToSignature(type.getKey(), KeyToSignature.SIGNATURE, true);
+		parser.parse();
+		return parser.toString();
 	}
 
 	/**
@@ -157,7 +167,7 @@
 		if (!targetType.exists())
 			return null;
 
-		String binaryTypeName = targetType.getFullyQualifiedName('.').replace('.', '/');
+		String binaryTypeName = targetType.getFullyQualifiedName('$').replace('.', '/');
 		
 		IPackageFragmentRoot packageRoot = (IPackageFragmentRoot) targetType.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
 		IClasspathEntry entry = packageRoot.getResolvedClasspathEntry();
@@ -214,20 +224,50 @@
 	 * @param monitor progress monitor to be passed through into file operations, or null if no reporting is desired
 	 * @throws CoreException if access to the file fails
 	 * @throws IOException if reading file content fails
+	 * @throws IllegalArgumentException if the annotatedReturnType does not structurally match to originalSignature
 	 */
 	public static void annotateMethodReturnType(String typeName, IFile file, String selector, String originalSignature,
 										String annotatedReturnType, MergeStrategy mergeStrategy, IProgressMonitor monitor)
-			throws CoreException, IOException
+			throws CoreException, IOException, IllegalArgumentException
 	{
 		annotateMember(typeName, file, selector, originalSignature, annotatedReturnType, POSITION_RETURN_TYPE, mergeStrategy, monitor);
 	}
 
-	static void annotateMember(String typeName, IFile file, String selector, String originalSignature, String annotatedSignature,
+	/**
+	 * Update the given external annotation file with details regarding annotations of a parameter type of a given method.
+	 * If the specified method already has external annotations, old and new annotations will be merged,
+	 * with priorities controlled by the parameter 'mergeStrategy'.
+	 * <p>
+	 * This method is suitable for declaration annotations and type use annotations.
+	 * </p>
+	 * @param typeName binary name (slash separated) of the type being annotated
+	 * @param file a file assumed to be in .eea format, will be created if it doesn't exist.
+	 * @param selector selector of the method
+	 * @param originalSignature unannotated signature of the member, used for identification
+	 * @param annotatedParameterType signature of the new parameter type whose annotations should be superimposed on the method
+	 * @param paramIdx 0-based index of the parameter to which the annotation should be attached
+	 * @param mergeStrategy controls how old and new signatures should be merged
+	 * @param monitor progress monitor to be passed through into file operations, or null if no reporting is desired
+	 * @throws CoreException if access to the file fails
+	 * @throws IOException if reading file content fails
+	 * @throws IllegalArgumentException if the annotatedParameterType does not structurally match to originalSignature
+	 */
+	public static void annotateMethodParameterType(String typeName, IFile file, String selector, String originalSignature,
+										String annotatedParameterType, int paramIdx, MergeStrategy mergeStrategy, IProgressMonitor monitor)
+			throws CoreException, IOException, IllegalArgumentException
+	{
+		annotateMember(typeName, file, selector, originalSignature, annotatedParameterType, paramIdx, mergeStrategy, monitor);
+	}
+
+	private static void annotateMember(String typeName, IFile file, String selector, String originalSignature, String annotatedSignature,
 										int updatePosition, MergeStrategy mergeStrategy, IProgressMonitor monitor)
-			throws CoreException, IOException
+			throws CoreException, IOException, IllegalArgumentException
 	{
 
 		if (!file.exists()) {
+			// assemble full annotatedSignature (don't bother merging since no previous signature exists):
+			annotatedSignature = updateSignature(originalSignature, annotatedSignature, updatePosition, MergeStrategy.REPLACE_SIGNATURE);
+
 			StringBuffer newContent= new StringBuffer();
 			// header:
 			newContent.append(ExternalAnnotationProvider.CLASS_PREFIX);
@@ -265,6 +305,9 @@
 					if (relation == 0) {
 						StringBuffer pending = new StringBuffer(line).append('\n');
 						pending.append(line = reader.readLine());
+						if (line == null) {
+							break; // found only the selector at EOF, append right here, ignoring 'pending'
+						}
 						// compare original signatures:
 						relation = line.trim().compareTo(originalSignature);
 						if (relation > 0) { // past the insertion point
@@ -277,28 +320,24 @@
 							continue;
 						if (relation == 0) {
 							// update existing entry:
-							String nextLine = reader.readLine();
-							if (nextLine == null)
-								nextLine = line; // no annotated line yet, use unannotated line instead
-							if (nextLine.startsWith(" ")) { //$NON-NLS-1$
+							String annotationLine = reader.readLine();
+							String nextLine = null;
+							if (annotationLine == null || annotationLine.isEmpty() || !annotationLine.startsWith(" ")) { //$NON-NLS-1$
+								nextLine = annotationLine; // push back, since not a signature line
+								annotationLine = line; // no annotated line yet, use unannotated line instead
+							}
+							if (annotationLine.startsWith(" ")) { //$NON-NLS-1$
 								switch (mergeStrategy) {
 									case REPLACE_SIGNATURE:
 										break; // unconditionally use annotatedSignature
 									case OVERWRITE_ANNOTATIONS:
 									case ADD_ANNOTATIONS:
-										if (updatePosition == POSITION_FULL_SIGNATURE) {
-											annotatedSignature = addAnnotationsTo(annotatedSignature, nextLine.trim(), mergeStrategy);
-										} else if (updatePosition == POSITION_RETURN_TYPE) {
-											annotatedSignature = updateMethodReturnType(annotatedSignature, nextLine.trim(), mergeStrategy);
-										} else {
-											// parameter i
-										}
+										annotatedSignature = updateSignature(annotationLine.trim(), annotatedSignature, updatePosition, mergeStrategy);
 										break;
 									default:
 										JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
 																				"Unexpected value for enum MergeStrategy")); //$NON-NLS-1$
 								}
-								nextLine = null; // discard old annotated signature (may have been merged above)
 							}
 							writeFile(file, newContent, annotatedSignature, nextLine, reader, monitor);
 							return;
@@ -308,13 +347,7 @@
 				// add new entry:
 				newContent.append(selector).append('\n');
 				newContent.append(' ').append(originalSignature).append('\n');
-				if (updatePosition == POSITION_FULL_SIGNATURE) {
-					// annotatedSignature is already complete
-				} else if (updatePosition == POSITION_RETURN_TYPE) {
-					annotatedSignature = updateMethodReturnType(annotatedSignature, originalSignature, mergeStrategy);
-				} else {
-					// parameter i
-				}
+				annotatedSignature = updateSignature(originalSignature, annotatedSignature, updatePosition, mergeStrategy);
 				writeFile(file, newContent, annotatedSignature, line, reader, monitor);
 			} finally {
 				reader.close();
@@ -322,6 +355,38 @@
 		}
 	}
 
+	private static String updateSignature(String originalSignature, String annotatedSignature, int updatePosition, MergeStrategy mergeStrategy) {
+		StringBuffer buf = new StringBuffer();
+		String signatureToReplace;
+		String postfix = null;
+		switch (updatePosition) {
+			case POSITION_FULL_SIGNATURE:
+				signatureToReplace = originalSignature;
+				break;
+			case POSITION_RETURN_TYPE:
+				assert originalSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
+				int close = originalSignature.indexOf(')');
+				buf.append(originalSignature, 0, close+1);
+				signatureToReplace = originalSignature.substring(close+1);
+				break;
+			default: // parameter
+				SignatureWrapper wrapper = new SignatureWrapper(originalSignature.toCharArray(), true, true); // may already contain annotations
+				wrapper.start = 1;
+				for (int i = 0; i < updatePosition; i++)
+					wrapper.start = wrapper.computeEnd() + 1;
+				int start = wrapper.start;
+				int end = wrapper.computeEnd();
+				end = wrapper.skipAngleContents(end);
+				buf.append(originalSignature, 0, start);
+				signatureToReplace = originalSignature.substring(start, end+1);
+				postfix = originalSignature.substring(end+1, originalSignature.length());
+		}
+		updateType(buf, signatureToReplace.toCharArray(), annotatedSignature.toCharArray(), mergeStrategy);
+		if (postfix != null)
+			buf.append(postfix);
+		return buf.toString();
+	}
+
 	/**
 	 * Insert that given annotation at the given position into the given signature. 
 	 * @param mergeStrategy if set to {@link MergeStrategy#ADD_ANNOTATIONS}, refuse to
@@ -342,96 +407,49 @@
 		return result.toString();
 	}
 
-	private static String addAnnotationsTo(String newSignature, String oldSignature, MergeStrategy mergeStategy) {
-		// TODO: consider rewrite using updateType() below
-		StringBuffer buf = new StringBuffer();
-		assert newSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
-		assert oldSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
-		buf.append('(');
-		SignatureWrapper wrapperNew = new SignatureWrapper(newSignature.toCharArray(), true); // when using annotations we must be at 1.5+
-		wrapperNew.start = 1;
-		SignatureWrapper wrapperOld = new SignatureWrapper(oldSignature.toCharArray(), true);
-		wrapperOld.start = 1;
-		while (!wrapperNew.atEnd() && !wrapperOld.atEnd()) {
-			int startNew = wrapperNew.start;
-			int startOld = wrapperOld.start;
-			if (wrapperNew.signature[startNew] == ')') {
-				if (wrapperOld.signature[startOld] != ')')
-					throw new IllegalArgumentException("Structural difference between signatures "+newSignature+" and "+oldSignature);  //$NON-NLS-1$//$NON-NLS-2$
-				startNew = ++wrapperNew.start;
-				startOld = ++wrapperOld.start;
-				buf.append(')');
-			}			
-			int endNew = wrapperNew.computeEnd();
-			int endOld = wrapperOld.computeEnd();
-			int lenNew = endNew-startNew+1;
-			int lenOld = endOld-startOld+1;
-			 // TODO detailed comparison / merging:
-			if (lenNew == lenOld) {
-				switch (mergeStategy) {
-					case OVERWRITE_ANNOTATIONS:
-						buf.append(wrapperNew.signature, startNew, lenNew);
-						break;
-					case ADD_ANNOTATIONS:
-						buf.append(wrapperOld.signature, startOld, lenOld);
-						break;
-					//$CASES-OMITTED$ should only be called with the two strategies handled above
-					default:
-						JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
-																"Unexpected value for enum MergeStrategy")); //$NON-NLS-1$
-				}
-			} else if (lenNew > lenOld) {
-				buf.append(wrapperNew.signature, startNew, lenNew);
-			} else {				
-				buf.append(wrapperOld.signature, startOld, lenOld);
-			}
-		}
-		return buf.toString();
-	}
-
-	private static String updateMethodReturnType(String newReturnType, String oldSignature, MergeStrategy mergeStrategy) {
-		StringBuffer buf = new StringBuffer();
-		assert oldSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
-		int close = oldSignature.indexOf(')');
-		buf.append(oldSignature, 0, close+1);
-		updateType(buf, oldSignature.substring(close+1).toCharArray(), newReturnType.toCharArray(), mergeStrategy);
-		return buf.toString();
-	}
-
 	/**
 	 * Update 'oldType' with annotations from 'newType' guided by 'mergeStrategy'.
 	 * The result is written into 'buf' as we go.
 	 */
 	private static boolean updateType(StringBuffer buf, char[] oldType, char[] newType, MergeStrategy mergeStrategy) {
-		SignatureWrapper oWrap = new SignatureWrapper(oldType, true);
-		SignatureWrapper nWrap = new SignatureWrapper(newType, true);
-		if (match(buf, oWrap, nWrap, 'L', false)
-			|| match(buf, oWrap, nWrap, 'T', false))
-		{
-			mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
-			buf.append(oWrap.nextName());
-			nWrap.nextName(); // skip
-			if (match(buf, oWrap, nWrap, '<', false)) {
-				do {
-					int oStart = oWrap.start;
-					int nStart = nWrap.start;
-					oWrap.computeEnd();
-					nWrap.computeEnd();
-					if (updateType(buf, oWrap.getFrom(oStart), nWrap.getFrom(nStart), mergeStrategy))
-						mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
-				} while (!match(buf, oWrap, nWrap, '>', false));
+		if (mergeStrategy == MergeStrategy.REPLACE_SIGNATURE) {
+			buf.append(newType);
+			return false;
+		}			
+		try {
+			SignatureWrapper oWrap = new SignatureWrapper(oldType, true, true); // may already contain annotations
+			SignatureWrapper nWrap = new SignatureWrapper(newType, true, true); // may already contain annotations
+			if (match(buf, oWrap, nWrap, 'L', false)
+				|| match(buf, oWrap, nWrap, 'T', false))
+			{
+				mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
+				buf.append(oWrap.nextName());
+				nWrap.nextName(); // skip
+				if (match(buf, oWrap, nWrap, '<', false)) {
+					do {
+						int oStart = oWrap.start;
+						int nStart = nWrap.start;
+						oWrap.computeEnd();
+						nWrap.computeEnd();
+						if (updateType(buf, oWrap.getFrom(oStart), nWrap.getFrom(nStart), mergeStrategy))
+							mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
+					} while (!match(buf, oWrap, nWrap, '>', false));
+				}
+				match(buf, oWrap, nWrap, ';', true);
+			} else if (match(buf, oWrap, nWrap, '[', false)) {
+				mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
+				updateType(buf, oWrap.tail(), nWrap.tail(), mergeStrategy);
+			} else if (match(buf, oWrap, nWrap, '*', false)
+					|| match(buf, oWrap, nWrap, '+', false)
+					|| match(buf, oWrap, nWrap, '-', false))
+			{
+				return true; // annotation allowed after this (not included in oldType / newType)
+			} else {			
+				buf.append(oldType);
 			}
-			match(buf, oWrap, nWrap, ';', true);
-		} else if (match(buf, oWrap, nWrap, '[', false)) {
-			mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
-			updateType(buf, oWrap.tail(), nWrap.tail(), mergeStrategy);
-		} else if (match(buf, oWrap, nWrap, '*', false)
-				|| match(buf, oWrap, nWrap, '+', false)
-				|| match(buf, oWrap, nWrap, '-', false))
-		{
-			return true; // annotation allowed after this (not included in oldType / newType)
-		} else {			
-			buf.append(oldType);
+		} catch (ArrayIndexOutOfBoundsException aioobe) { // from several locations inside match() or mergeAnnotation().
+			StringBuilder msg = new StringBuilder("Structural mismatch between ").append(oldType).append(" and ").append(newType); //$NON-NLS-1$ //$NON-NLS-2$
+			throw new IllegalArgumentException(msg.toString(), aioobe);
 		}
 		return false;
 	}
@@ -444,8 +462,9 @@
 		boolean match1 = sig1.signature[sig1.start] == expected;
 		boolean match2 = sig2.signature[sig2.start] == expected;
 		if (match1 != match2) {
-			throw new IllegalArgumentException("Mismatching type structures" //$NON-NLS-1$
-					+ new String(sig1.signature)+" vs "+new String(sig2.signature)); //$NON-NLS-1$ 
+			StringBuilder msg = new StringBuilder("Mismatching type structures ") //$NON-NLS-1$
+									.append(sig1.signature).append(" vs ").append(sig2.signature); //$NON-NLS-1$
+			throw new IllegalArgumentException(msg.toString()); 
 		}
 		if (match1) {
 			buf.append(expected);
@@ -486,9 +505,18 @@
 						break;
 					case NO_ANNOTATION:
 						newS.start++; // don't insert
-						switch (oldAnn) { case NULLABLE: case NONNULL: oldS.start++; } // just skip // skip
+						switch (oldAnn) { case NULLABLE: case NONNULL: oldS.start++; } // just skip
 						break;
+					default:
+						switch (oldAnn) { 
+							case NULLABLE: case NONNULL: 
+								oldS.start++;
+								buf.append(oldAnn); // keep
+						}
 				}
+				break;
+			default:
+				throw new IllegalArgumentException("Unexpected merge strategy"); // REPLACE_SIGNATURE does not reach this point, see initial check in updateType() //$NON-NLS-1$
 		}
 	}
 
@@ -532,4 +560,129 @@
 		}
 		((IFolder) container).create(false, true, monitor);
 	}
+
+	/**
+	 * Retrieve the annotated signature of a specified member as found in the given external annotation file, if any.
+	 * @param typeName fully qualified slash-separated name of the type for which the file defines external annotations
+	 * @param file a file assumed to be in .eea format, must not be null, but may not exist
+	 * @param selector name of the member whose annotation we are looking for
+	 * @param originalSignature the unannotated signature by which the member is identified
+	 * @return the annotated signature as found in the file, or null.
+	 */
+	public static String getAnnotatedSignature(String typeName, IFile file, String selector, String originalSignature) {
+		if (file.exists()) {
+			try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()))) {
+				ExternalAnnotationProvider.assertClassHeader(reader.readLine(), typeName);
+				while (true) {
+					String line = reader.readLine();
+					// selector:
+					if (selector.equals(line)) {
+						// original signature:
+						line = reader.readLine();
+						if (originalSignature.equals(ExternalAnnotationProvider.extractSignature(line))) {
+							// annotated signature:
+							return ExternalAnnotationProvider.extractSignature(reader.readLine());
+						}
+					}
+					if (line == null)
+						break;
+				}
+			} catch (IOException | CoreException e) {
+				return null;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Apply the specified changes on the given type.
+	 * This method can be used as a dry run without modifying an annotation file.
+	 * 
+	 * @param originalSignature the original type signature, may be annotated already
+	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
+	 * @param mergeStrategy controls how old and new signatures should be merged
+	 * @return an array of length four: <ul>
+	 * <li>prefix up-to the changed type</li>
+	 * <li>original type</li>
+	 * <li>changed type</li>
+	 * <li>postfix after the changed type <em>(here: empty string)</li>
+	 * </ul>
+	 */
+	public static String[] annotateType(String originalSignature, String annotatedType, MergeStrategy mergeStrategy)
+	{
+		String[] result = new String[4]; // prefix, orig, replacement, postfix
+		StringBuffer buf;
+		result[0] = ""; //$NON-NLS-1$
+		buf = new StringBuffer();
+		result[1] = originalSignature;
+		updateType(buf, originalSignature.toCharArray(), annotatedType.toCharArray(), mergeStrategy);
+		result[2] = buf.toString();
+		result[3] = ""; //$NON-NLS-1$
+		return result;
+	}
+
+	/**
+	 * Apply the specified changes on the return type of the given signature.
+	 * This method can be used as a dry run without modifying an annotation file.
+	 * 
+	 * @param originalSignature the original full signature, may be annotated already
+	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
+	 * @param mergeStrategy controls how old and new signatures should be merged
+	 * @return an array of length four: <ul>
+	 * <li>prefix up-to the changed type</li>
+	 * <li>original type</li>
+	 * <li>changed type</li>
+	 * <li>postfix after the changed type <em>(here: empty string)</li>
+	 * </ul>
+	 */
+	public static String[] annotateReturnType(String originalSignature, String annotatedType, MergeStrategy mergeStrategy)
+	{
+		String[] result = new String[4]; // prefix, orig, replacement, postfix
+		StringBuffer buf;
+		assert originalSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
+		int close = originalSignature.indexOf(')');
+		result[0] = originalSignature.substring(0, close+1);
+		buf = new StringBuffer();
+		result[1] = originalSignature.substring(close+1);
+		updateType(buf, result[1].toCharArray(), annotatedType.toCharArray(), mergeStrategy);
+		result[2] = buf.toString();
+		result[3] = ""; //$NON-NLS-1$
+		return result;
+	}
+	
+
+	/**
+	 * Apply the specified changes on a parameter within the given signature.
+	 * This method can be used as a dry run without modifying an annotation file.
+	 * 
+	 * @param originalSignature the original full signature, may be annotated already
+	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
+	 * @param paramIdx the index of a parameter to annotated
+	 * @param mergeStrategy controls how old and new signatures should be merged
+	 * @return an array of length four: <ul>
+	 * <li>prefix up-to the changed type</li>
+	 * <li>original type</li>
+	 * <li>changed type</li>
+	 * <li>postfix after the changed type</li>
+	 * </ul>
+	 */
+	public static String[] annotateParameterType(String originalSignature, String annotatedType, int paramIdx, MergeStrategy mergeStrategy)
+	{
+		String[] result = new String[4]; // prefix, orig, replacement, postfix
+		StringBuffer buf;
+		SignatureWrapper wrapper = new SignatureWrapper(originalSignature.toCharArray(), true, true); // may already contain annotations
+		wrapper.start = 1;
+		for (int i = 0; i < paramIdx; i++)
+			wrapper.start = wrapper.computeEnd() + 1;
+		int start = wrapper.start;
+		int end = wrapper.computeEnd();
+		end = wrapper.skipAngleContents(end);
+		result[0] = originalSignature.substring(0, start);				
+		buf = new StringBuffer();
+		result[1] = originalSignature.substring(start, end+1);
+		updateType(buf, result[1].toCharArray(), annotatedType.toCharArray(), mergeStrategy);
+		result[2] = buf.toString();
+		result[3] = originalSignature.substring(end+1, originalSignature.length());
+		return result;
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
index ebbc201..47343ab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
@@ -9,6 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *	   Stephan Herrmann - Contribution for
  *								Bug 425183 - [1.8][inference] make CaptureBinding18 safe
+ *								Bug 462025 - [null][test] create tests for manipulating external null annotations
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.util;
 
@@ -32,6 +33,7 @@
 
 	public StringBuffer signature = new StringBuffer();
 	private int kind;
+	private boolean asBinarySignature = false; // '.' vs. '/' and '$'
 	private ArrayList arguments = new ArrayList();
 	private ArrayList typeArguments = new ArrayList();
 	private ArrayList typeParameters = new ArrayList();
@@ -42,7 +44,9 @@
 
 	public KeyToSignature(BindingKeyParser parser) {
 		super(parser);
-		this.kind = ((KeyToSignature) parser).kind;
+		KeyToSignature keyToSignature = (KeyToSignature) parser;
+		this.kind = keyToSignature.kind;
+		this.asBinarySignature = keyToSignature.asBinarySignature;
 	}
 
 	public KeyToSignature(String key, int kind) {
@@ -50,6 +54,12 @@
 		this.kind = kind;
 	}
 
+	public KeyToSignature(String key, int kind, boolean asBinarySignature) {
+		super(key);
+		this.kind = kind;
+		this.asBinarySignature = asBinarySignature;
+	}
+
 	public void consumeArrayDimension(char[] brakets) {
 		this.signature.append(brakets);
 	}
@@ -74,14 +84,16 @@
 		this.signature = new StringBuffer();
 		// remove trailing semi-colon as it is added later in comsumeType()
 		uniqueKey = CharOperation.subarray(uniqueKey, 0, uniqueKey.length-1);
-		CharOperation.replace(uniqueKey, '/', '.');
+		if (!this.asBinarySignature)
+			CharOperation.replace(uniqueKey, '/', '.');
 		this.signature.append(uniqueKey);
 	}
 
 	public void consumeMethod(char[] selector, char[] methodSignature) {
 		this.arguments = new ArrayList();
 		this.typeArguments = new ArrayList();
-		CharOperation.replace(methodSignature, '/', '.');
+		if (!this.asBinarySignature)
+			CharOperation.replace(methodSignature, '/', '.');
 		switch(this.kind) {
 			case SIGNATURE:
 				this.signature = new StringBuffer();
@@ -198,7 +210,7 @@
 	public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
 		if (simpleTypeName != null) {
 			// member type
-			this.signature.append('.');
+			this.signature.append(this.asBinarySignature ? '$' : '.');
 			this.signature.append(simpleTypeName);
 		}
 		if (!isRaw) {
@@ -237,12 +249,14 @@
 	public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
 		this.typeSigStart = this.signature.length();
 		this.signature.append('L');
-		this.signature.append(CharOperation.replaceOnCopy(fullyQualifiedName, '/', '.'));
+		if (!this.asBinarySignature)
+			fullyQualifiedName = CharOperation.replaceOnCopy(fullyQualifiedName, '/', '.');
+		this.signature.append(fullyQualifiedName);
 	}
 
 	public void consumeSecondaryType(char[] simpleTypeName) {
 		this.signature.append('~');
-		this.mainTypeStart = this.signature.lastIndexOf(".") + 1; //$NON-NLS-1$
+		this.mainTypeStart = this.signature.lastIndexOf(this.asBinarySignature ? "/" : ".") + 1; //$NON-NLS-1$ //$NON-NLS-2$
 		if (this.mainTypeStart == 0) {
 			this.mainTypeStart = 1; // default package (1 for the 'L')
 			int i = 0;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
index a234f40..fb6d3fb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
 import org.eclipse.jdt.core.search.SearchMatch;
 import org.eclipse.jdt.core.search.SearchPattern;
 import org.eclipse.jdt.internal.compiler.ast.*;
@@ -44,6 +45,7 @@
 	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
 }
 public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) {
+	if (this.pattern.fineGrain != 0 && !this.pattern.findDeclarations) return IMPOSSIBLE_MATCH;
 	int referencesLevel = this.pattern.findReferences ? matchLevelForReferences(node) : IMPOSSIBLE_MATCH;
 	int declarationsLevel = this.pattern.findDeclarations ? matchLevelForDeclarations(node) : IMPOSSIBLE_MATCH;
 
@@ -100,6 +102,10 @@
 public int match(TypeDeclaration node, MatchingNodeSet nodeSet) {
 	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
 
+	if (this.pattern.fineGrain != 0 && 
+			(this.pattern.fineGrain & ~IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION) == 0 )
+		return IMPOSSIBLE_MATCH;
+
 	// need to look for a generated default constructor
 	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
 }