update jdt.core to I20190801-1800 for 2019-09 M2
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index fc53e87..8e410c7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -558,6 +558,15 @@
 			options.setCompilerOptions("-source 1."+release+" -target 1."+release);
 		return options;
 	}
+	@java.lang.SuppressWarnings("synthetic-access")
+	static JavacTestOptions forReleaseWithPreview(String release) {
+		JavacTestOptions options = new JavacTestOptions(Long.parseLong(release));
+		if (isJRE9Plus)
+			options.setCompilerOptions("--release "+release+" --enable-preview -Xlint:-preview");
+		else
+			throw new IllegalArgumentException("preview not supported at release "+release);
+		return options;
+	}
 	public static class SuppressWarnings extends JavacTestOptions {
 		public SuppressWarnings(String token) {
 			setCompilerOptions("-Xlint:-"+token);
@@ -938,7 +947,9 @@
 			JavacBug6337964 = RUN_JAVAC ? // https://bugs.eclipse.org/bugs/show_bug.cgi?id=112433
 					new JavacHasABug(MismatchType.JavacErrorsEclipseNone, ClassFileConstants.JDK1_6, 1045/*guessed*/, true) : null,
 			JavacBug8144832 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8144832
-					new JavacHasABug(MismatchType.JavacErrorsEclipseNone, ClassFileConstants.JDK9, 0000) : null;
+					new JavacHasABug(MismatchType.JavacErrorsEclipseNone, ClassFileConstants.JDK9, 0000) : null,
+			JavacBug8179483_switchExpression = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8179483
+					new JavacBug8179483(" --release 12 --enable-preview -Xlint:-preview") : null;
 
 		// bugs that have been fixed but that we've not identified
 		public static JavacHasABug
@@ -972,6 +983,17 @@
 							}
 					}: null;
 	}
+	public static class JavacBug8179483 extends JavacHasABug {
+		String extraJavacOptions;
+		public JavacBug8179483(String extraJavacOptions) {
+			super(MismatchType.EclipseErrorsJavacWarnings);
+			this.extraJavacOptions = extraJavacOptions;
+		}
+		@Override
+		String getCompilerOptions() {
+			return super.getCompilerOptions() + this.extraJavacOptions;
+		}
+	}
 }
 
 // PREMATURE: Logger helps us monitor processes outputs (standard and error);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
index 5deac45..0eb6a28 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
@@ -3346,6 +3346,81 @@
 		},
 		"SUCCESS");
 }
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=548647 JDT reports unnecessary cast, using the Quickfix to remove it creates syntax error
+public void test548647() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_5)
+		return;
+	Map customOptions = getCompilerOptions();
+	customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.ERROR);
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"interface MUIElement {}\n" + 
+			"interface MUIElementContainer<T extends MUIElement> extends MUIElement{}\n" + 
+			"interface MWindowElement extends MUIElement {}\n" + 
+			"interface MWindow extends MUIElementContainer<MWindowElement> {}\n" + 
+			"public class X {\n" +
+			"	MUIElementContainer<MUIElement> field;\n" +
+			"	MUIElementContainer<MUIElement> getField() {\n" +
+			"		return field;\n" +
+			"	}\n" +
+			"	void test(MUIElementContainer<MUIElement> me) {\n" +
+			"		MUIElementContainer<MUIElement> localVar = me;\n" +
+			"		if ((Object) localVar instanceof MWindow) return;\n" +
+			"		if(((Object) me) instanceof MWindow) return;\n" +
+			"		if ((MUIElement)field instanceof MWindow) return;\n" +
+			"		if ((MUIElement)getField() instanceof MWindow) return;\n" +
+			"		MWindow mw = (MWindow)((MUIElement)me);\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		customOptions);
+}
+public void test548647a() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_5)
+		return;
+	Runner runner = new Runner();
+	runner.customOptions = getCompilerOptions();
+	runner.customOptions.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.WARNING);
+	runner.testFiles =
+		new String[] {
+			"Bug.java",
+			"public class Bug {\n" +
+			"	Integer k;\n" +
+			"	private Number getK() { return k; }\n" +
+			"	public void fn(Number n) {\n" + 
+			"		Number j = n;\n" +
+			"		if ((Number) n instanceof Long) return;\n" +
+			"		if ((Number) k instanceof Integer) return;\n" +
+			"		if ((Number) j instanceof Integer) return;\n" +
+			"		if ((Number) getK() instanceof Integer) return;\n" +
+			"	}\n" + 
+			"}"
+		};
+	runner.expectedCompilerLog =
+			"----------\n" +
+			"1. WARNING in Bug.java (at line 6)\n" +
+			"	if ((Number) n instanceof Long) return;\n" +
+			"	    ^^^^^^^^^^\n" +
+			"Unnecessary cast from Number to Number\n" +
+			"----------\n" +
+			"2. WARNING in Bug.java (at line 7)\n" +
+			"	if ((Number) k instanceof Integer) return;\n" +
+			"	    ^^^^^^^^^^\n" +
+			"Unnecessary cast from Integer to Number\n" +
+			"----------\n" +
+			"3. WARNING in Bug.java (at line 8)\n" +
+			"	if ((Number) j instanceof Integer) return;\n" +
+			"	    ^^^^^^^^^^\n" +
+			"Unnecessary cast from Number to Number\n" +
+			"----------\n" +
+			"4. WARNING in Bug.java (at line 9)\n" +
+			"	if ((Number) getK() instanceof Integer) return;\n" +
+			"	    ^^^^^^^^^^^^^^^\n" +
+			"Unnecessary cast from Number to Number\n" +
+			"----------\n";
+	runner.runWarningTest();
+}
 
 public static Class testClass() {
 	return CastTest.class;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
index c3bbba2..dc2e38b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2017 GK Software AG, IBM Corporation and others.
+ * Copyright (c) 2013, 2019 GK Software AG, IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -3118,4 +3118,33 @@
 			"The default method foo() inherited from JavaTest.D conflicts with another method inherited from JavaTest.C\n" +
 			"----------\n");
 	}
+
+	public void testBug539743() {
+		runConformTest(
+		new String[] {
+			"Test.java",
+			"public class Test {\n" + 
+			"	static <V> void m(V v) {\n" + 
+			"\n" + 
+			"	}\n" + 
+			"\n" + 
+			"	interface Foo {\n" + 
+			"		@SuppressWarnings(\"unchecked\")\n" + 
+			"		default <U> U f() {\n" + 
+			"			return (U) new Object();\n" + 
+			"		}\n" + 
+			"	}\n" + 
+			"\n" + 
+			"	static class Bar implements Foo {\n" + 
+			"		@SuppressWarnings(\"unchecked\")\n" + 
+			"		@Override\n" + 
+			"		public Object f() {\n" + 
+			"			m(Foo.super.f());\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 7e26543..b13e295 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2018 IBM Corporation and others.
+ * Copyright (c) 2015, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -15,6 +15,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.EclipseHasABug;
 import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.JavacHasABug;
 
@@ -1121,6 +1122,47 @@
 		},
 		"Done");
 }
+public void testBug543778() {
+	Runner runner = new Runner();
+	runner.testFiles =
+		new String[] {
+			"Sandbox.java",
+			"import java.util.function.Supplier;\n" + 
+			"\n" + 
+			"public class Sandbox {\n" + 
+			"\n" + 
+			"    <R extends Object> R get(Supplier<@NonNull R> impl) {\n" + 
+			"        return null;\n" + 
+			"    }\n" + 
+			"\n" + 
+			"    Object getter() {\n" + 
+			"        return get(() -> new Object() {\n" + 
+			"\n" + 
+			"            @Override\n" + 
+			"            public String toString() {\n" + 
+			"                return super.toString();\n" + 
+			"            }\n" + 
+			"\n" + 
+			"        });\n" + 
+			"    }\n" + 
+			"\n" + 
+			"}\n",
+			"NonNull.java",
+			"import java.lang.annotation.ElementType;\n" + 
+			"import java.lang.annotation.Retention;\n" + 
+			"import java.lang.annotation.RetentionPolicy;\n" + 
+			"import java.lang.annotation.Target;\n" + 
+			"\n" + 
+			"@Retention(RetentionPolicy.CLASS)\n" + 
+			"@Target({ ElementType.TYPE_USE })\n" + 
+			"public @interface NonNull {\n" + 
+			"    // marker annotation with no members\n" + 
+			"}\n",
+		};
+	runner.customOptions = getCompilerOptions();
+	runner.customOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED); // bug happens due to type annotation handling
+	runner.runConformTest();
+}
 public static Class testClass() {
 	return LambdaRegressionTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationBatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationBatchCompilerTest.java
index d2d8433..f40a8aa 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationBatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationBatchCompilerTest.java
@@ -308,7 +308,7 @@
 			+ " -1.5"
 			+ " -warn:+nullAnnot(foo|bar) -warn:+null -nonNullByDefault -proc:none -d \"" + OUTPUT_DIR + "\"",
 			"",
-			"Token nullAnnot(foo|bar) is not in the expected format \"nullAnnot(<non null annotation name> | <nullable annotation name> | <non-null by default annotation name>)\"\n",
+			"Token nullAnnot(foo|bar) is not in the expected format \"nullAnnot(<nullable annotation name> | <non null annotation name> | <non-null by default annotation name>)\"\n",
 			true);
 	}
 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index 8649fd7..df38525 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -18265,4 +18265,27 @@
 			"----------\n";
 	runner.runNegativeTest();
 }
+public void testBug544872() {
+	runNegativeNullTest(
+		new String[] {
+			"Test.java",
+			"public class Test {\n" + 
+			"    static void f(String string) {\n" + 
+			"        if (string != null)\n" + 
+			"            string.hashCode();\n" + 
+			"        synchronized (string) {\n" + 
+			"            string.hashCode();\n" + 
+			"        }\n" + 
+			"    }\n" + 
+			"}\n" + 
+			""
+		}, 
+		"----------\n" + 
+		"1. ERROR in Test.java (at line 5)\n" + 
+		"	synchronized (string) {\n" + 
+		"	              ^^^^^^\n" + 
+		"Potential null pointer access: The variable string may be null at this location\n" + 
+		"----------\n"
+	);
+}
 }
\ No newline at end of file
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 f440a44..17ef64b 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
@@ -17819,4 +17819,25 @@
 			"----------\n";
 	runner.runNegativeTest();
 }
+public void testBug499714() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"Type.java",
+			"import org.eclipse.jdt.annotation.*;\n" + 
+			"\n" + 
+			"interface Type<@Nullable K> {\n" + 
+			"    K get();\n" + 
+			"\n" + 
+			"    static <@Nullable T> void x(Type<T> t) {\n" + 
+			"        t.get().toString();\n" + 
+			"    }\n" + 
+			"}"
+		}, 
+		"----------\n" + 
+		"1. ERROR in Type.java (at line 7)\n" + 
+		"	t.get().toString();\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The method get() may return null\n" + 
+		"----------\n");
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
index a936514..7ef1d2e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
@@ -14,6 +14,7 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.JavacHasABug;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
@@ -46,16 +47,36 @@
 		defaultOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
 		return defaultOptions;
 	}
-	
+
 	@Override
-	protected void runConformTest(String[] testFiles, Map customOptions) {
-		super.runConformTest(testFiles, "", null, true, new String[] {"--enable-preview"}, customOptions, null);
+	protected void runConformTest(String[] testFiles, String expectedOutput) {
+		runConformTest(testFiles, expectedOutput, getCompilerOptions());
 	}
 
 	@Override
 	protected void runConformTest(String[] testFiles, String expectedOutput, Map customOptions) {
-		super.runConformTest(testFiles, expectedOutput, null, true, new String[] {"--enable-preview"}, customOptions, null);
+		Runner runner = new Runner();
+		runner.testFiles = testFiles;
+		runner.expectedOutputString = expectedOutput;
+		runner.vmArguments = new String[] {"--enable-preview"};
+		runner.customOptions = customOptions;
+		runner.javacTestOptions = JavacTestOptions.forReleaseWithPreview("12");
+		runner.runConformTest();
 	}
+	@Override
+	protected void runNegativeTest(String[] testFiles, String expectedCompilerLog) {
+		runNegativeTest(testFiles, expectedCompilerLog, JavacTestOptions.forReleaseWithPreview("12"));
+	}
+	protected void runWarningTest(String[] testFiles, String expectedCompilerLog, Map<String, String> customOptions) {
+		Runner runner = new Runner();
+		runner.testFiles = testFiles;
+		runner.expectedCompilerLog = expectedCompilerLog;
+		runner.customOptions = customOptions;
+		runner.vmArguments = new String[] {"--enable-preview"};
+		runner.javacTestOptions = JavacTestOptions.forReleaseWithPreview("12");
+		runner.runWarningTest();
+	}
+
 	public void testSimpleExpressions() {
 		runConformTest(
 				new String[] {
@@ -74,9 +95,7 @@
 						"	}\n" +
 						"}\n"
 				},
-				"3",
-				null,
-				new String[] {"--enable-preview"});
+				"3");
 	}
 	public void testSwitchExpression_531714_002() {
 		runConformTest(
@@ -108,9 +127,7 @@
 								"	}\n"+
 								"}\n"
 				},
-				"Got Exception - expected",
-				null,
-				new String[] {"--enable-preview"});
+				"Got Exception - expected");
 	}
 	public void testBug531714_error_003() {
 		this.runNegativeTest(
@@ -265,9 +282,7 @@
 						"	}\n"+
 						"}\n"
 				},
-				"100",
-				null,
-				new String[] {"--enable-preview"});
+				"100");
 	}
 	public void testBug531714_008() {
 		Map<String, String> disablePreviewOptions = getCompilerOptions();
@@ -340,10 +355,7 @@
 				"	}\n" +
 				"}\n"
 			},
-			"hello",
-			null,
-			false,
-			new String[] { "--enable-preview"});
+			"hello");
 	}
 	public void testBug531714_009() {
 		Map<String, String> disablePreviewOptions = getCompilerOptions();
@@ -456,10 +468,7 @@
 				"----------\n";
 		this.runNegativeTest(
 				testFiles,
-				expectedProblemLog,
-				null,
-				true,
-				getCompilerOptions());
+				expectedProblemLog);
 	}
 	public void testBug531714_012() {
 		Map<String, String> options = getCompilerOptions();
@@ -568,6 +577,7 @@
 				"	 ^\n" + 
 				"Syntax error on token \".\", , expected\n" + 
 				"----------\n";
+		runner.javacTestOptions = JavacTestOptions.forReleaseWithPreview("12");
 		runner.runNegativeTest();
 	}
 	public void testBug543673_001() {
@@ -593,10 +603,7 @@
 				"	MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
 				"}\n"
 			},
-			"6",
-			null,
-			false,
-			new String[] { "--enable-preview"});
+			"6");
 	}
 	/*
 	 * A simple multi constant case statement, compiled and run as expected
@@ -624,13 +631,11 @@
 						"enum Day { SATURDAY, SUNDAY, MONDAY;}",
 		};
 
-		String expectedProblemLog =
+		String expectedOutput =
 				"SUNDAY";
 		this.runConformTest(
 				testFiles,
-				expectedProblemLog,
-				options,
-				new String[] { "--enable-preview"});
+				expectedOutput);
 	}
 	/*
 	 * A simple multi constant case statement, compiler reports missing enum constants
@@ -664,12 +669,9 @@
 						"	        ^^^\n" + 
 						"The enum constant TUESDAY needs a corresponding case label in this enum switch on Day\n" + 
 						"----------\n";
-		this.runNegativeTest(
+		this.runWarningTest(
 				testFiles,
 				expectedProblemLog,
-				null,
-				true,
-				new String[] { "--enable-preview"},
 				options);
 	}
 	/*
@@ -803,12 +805,9 @@
 				"	        ^^^\n" + 
 				"The enum constant MONDAY needs a corresponding case label in this enum switch on Day\n" + 
 				"----------\n";
-		this.runNegativeTest(
+		this.runWarningTest(
 				testFiles,
 				expectedProblemLog,
-				null,
-				true,
-				new String[] {"--enable-preview"},
 				options);
 	}
 	public void testBug543240_4() {
@@ -843,8 +842,7 @@
 		this.runConformTest(
 				testFiles,
 				expectedProblemLog,
-				options,
-				new String[] {"--enable-preview"});
+				options);
 	}
 	/*
 	 * Simple switch case with string literals
@@ -923,8 +921,7 @@
 		this.runConformTest(
 				testFiles,
 				expectedProblemLog,
-				options,
-				new String[] {"--enable-preview"});
+				options);
 	}
 	/*
 	 * Switch with multi constant case statements with string literals
@@ -965,8 +962,7 @@
 		this.runConformTest(
 				testFiles,
 				expectedProblemLog,
-				options,
-				new String[] {"--enable-preview"});
+				options);
 	}
 	/*
 	 * Switch with multi constant case statements with integer constants
@@ -1008,8 +1004,7 @@
 		this.runConformTest(
 				testFiles,
 				expectedProblemLog,
-				options,
-				new String[] {"--enable-preview"});
+				options);
 	}
 	/*
 	 * Switch multi-constant with mixed constant types, reported
@@ -1084,12 +1079,9 @@
 				"	^^^^^^^^^\n" + 
 				"Switch case may be entered by falling through previous case. If intended, add a new comment //$FALL-THROUGH$ on the line above\n" + 
 				"----------\n";
-		this.runNegativeTest(
+		this.runWarningTest(
 				testFiles,
 				expectedProblemLog,
-				null,
-				true,
-				new String[] { "--enable-preview"},
 				options);
 	}
 	/*
@@ -1122,12 +1114,9 @@
 				"	        ^\n" + 
 				"The switch statement should have a default case\n" + 
 				"----------\n";
-		this.runNegativeTest(
+		this.runWarningTest(
 				testFiles,
 				expectedProblemLog,
-				null,
-				true,
-				new String[] { "--enable-preview"},
 				options);
 	}
 	/*
@@ -1294,12 +1283,9 @@
 				"	}\n" + 
 				"}\n",
 		};
-		this.runNegativeTest(
+		this.runConformTest(
 				testFiles,
 				"",
-				null,
-				true,
-				new String[] { "--enable-preview"},
 				options);
 	}
 	public void testBug543795_01() {
@@ -1538,9 +1524,7 @@
 					"}"
 			},
 			"inside foo\n"
-			+ "0",
-			null,
-			new String[] {"--enable-preview"});
+			+ "0");
 	}
 	public void testSwitchStatementWithEnumValues() {
 		runConformTest(
@@ -1566,9 +1550,7 @@
 					"}\n" + 
 					""
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug543967_01() {
 		Map<String, String> options = getCompilerOptions();
@@ -1621,9 +1603,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug544204_2() {
 		runConformTest(
@@ -1643,9 +1623,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"10",
-			null,
-			new String[] {"--enable-preview"});
+			"10");
 	}
 	public void testBug544223() {
 		runConformTest(
@@ -1669,9 +1647,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug544258_01() {
 		this.runNegativeTest(
@@ -1728,9 +1704,7 @@
 					"    }\n" + 
 					"}"
 			},
-			"false",
-			null,
-			new String[] {"--enable-preview"});
+			"false");
 	}
 	public void testBug544254() {
 		runConformTest(
@@ -1752,9 +1726,7 @@
 					"    }\n" + 
 					"}"
 			},
-			"hello",
-			null,
-			new String[] {"--enable-preview"});
+			"hello");
 	}
 	public void testBug544254_2() {
 		Map<String, String> customOptions = getCompilerOptions();
@@ -1778,9 +1750,7 @@
 					"    }\n" + 
 					"}"
 			},
-			"hello",
-			customOptions,
-			new String[] {"--enable-preview"});
+			"hello");
 	}
 	public void testBug544254_3() {
 		Map<String, String> customOptions = getCompilerOptions();
@@ -1804,9 +1774,7 @@
 					"    }\n" + 
 					"}"
 			},
-			"hello",
-			customOptions,
-			new String[] {"--enable-preview"});
+			"hello");
 	}
 	public void testBug544224_1() {
 		Map<String, String> customOptions = getCompilerOptions();
@@ -1828,8 +1796,7 @@
 					"}\n"
 			},
 			"",
-			customOptions,
-			new String[] {"--enable-preview"});
+			customOptions);
 	}
 	public void testBug544298() {
 		runConformTest(
@@ -1852,9 +1819,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"i:1",
-			null,
-			new String[] {"--enable-preview"});
+			"i:1");
 	}
 	public void testBug544298_2() {
 		runConformTest(
@@ -1878,9 +1843,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"i:1",
-			null,
-			new String[] {"--enable-preview"});
+			"i:1");
 	}
 	public void testBug544428_01() {
 		Map<String, String> options = getCompilerOptions();
@@ -1937,9 +1900,7 @@
 					"    }\n" +
 					"}"
 			},
-			"0",
-			null,
-			new String[] {"--enable-preview"});
+			"0");
 	}
 	public void testBug544560_01() {
 		runConformTest(
@@ -1961,9 +1922,7 @@
 					"    }\n" +
 					"}\n"
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug544458() {
 		runConformTest(
@@ -1982,9 +1941,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug544458_2() {
 		runConformTest(
@@ -2003,9 +1960,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"0",
-			null,
-			new String[] {"--enable-preview"});
+			"0");
 	}
 	public void testBug544458_3() {
 		runConformTest(
@@ -2024,9 +1979,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"0",
-			null,
-			new String[] {"--enable-preview"});
+			"0");
 	}
 	public void testBug544458_4() {
 		runConformTest(
@@ -2045,9 +1998,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"0",
-			null,
-			new String[] {"--enable-preview"});
+			"0");
 	}
 	public void testBug544458_5() {
 		runConformTest(
@@ -2066,9 +2017,7 @@
 					"	}\n" + 
 					"}"
 			},
-			"0",
-			null,
-			new String[] {"--enable-preview"});
+			"0");
 	}
 	public void testBug544601_1() {
 		runConformTest(
@@ -2097,9 +2046,7 @@
 					"    }\n" +
 					"}\n"
 			},
-			"1",
-			null,
-			new String[] {"--enable-preview"});
+			"1");
 	}
 	public void testBug544556() {
 		runConformTest(
@@ -2123,9 +2070,7 @@
 				"	}\n" + 
 				"}"
 		},
-		"1",
-		null,
-		new String[] {"--enable-preview"});
+		"1");
 	}
 	public void testBug544702_01() {
 		runConformTest(
@@ -2147,9 +2092,7 @@
 				"\n" +
 				"}\n"
 		},
-		"Success",
-		null,
-		new String[] {"--enable-preview"});
+		"Success");
 	}
 	public void testBug545168_01() {
 		runConformTest(
@@ -2175,9 +2118,7 @@
 				"	MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" +
 				"}\n"
 		},
-		"9",
-		null,
-		new String[] {"--enable-preview"});
+		"9");
 	}
 	public void testBug545255_01() {
 		runConformTest(
@@ -2199,14 +2140,12 @@
 				"	}\n"+
 				"}\n"
 		},
-		"0",
-		null,
-		new String[] {"--enable-preview"});
+		"0");
 	}
 	// see comment 12 in the bug 
 	public void testBug513766_01() {
-		this.runNegativeTest(
-			new String[] {
+		Runner runner = new Runner();
+		runner.testFiles = new String[] {
 				"X.java",
 				"public class X {\n"+
 				"    @SuppressWarnings(\"preview\")\n"+
@@ -2217,8 +2156,8 @@
 				"            System.out.println(\"true, too\");\n"+
 				"    }\n"+
 				"    <T> T magic() { return null; }\n"+
-				"}\n",
-			},
+				"}\n"};
+		runner.expectedCompilerLog =
 			"----------\n" + 
 			"1. ERROR in X.java (at line 4)\n" + 
 			"	if (switch(i) { default -> magic(); })\n" + 
@@ -2229,7 +2168,10 @@
 			"	if (magic())\n" + 
 			"	    ^^^^^^^\n" + 
 			"Type mismatch: cannot convert from Object to boolean\n" + 
-			"----------\n");
+			"----------\n";
+		runner.vmArguments = new String[] {"--enable-preview"};
+		runner.javacTestOptions = JavacHasABug.JavacBug8179483_switchExpression;
+		runner.runNegativeTest();
 	}
 	public void testBug545333() {
 		runNegativeTest(
@@ -2283,7 +2225,7 @@
 				"Dead code\n" + 
 				"----------\n";
 		
-		this.runNegativeTest(new String[] {
+		this.runWarningTest(new String[] {
 				"X.java",
 				"public class X {\n" +
 				"  public static void main(String [] args) {\n" +
@@ -2295,9 +2237,6 @@
 				"}\n"
 			},
 			message,
-			null,
-			true,
-			new String[] { "--enable-preview"},
 			options);
 	}
 	public void testBug545518a() {
@@ -2314,7 +2253,7 @@
 				"Dead code\n" + 
 				"----------\n";
 		
-		this.runNegativeTest(new String[] {
+		this.runWarningTest(new String[] {
 				"X.java",
 				"public class X {\n" +
 				"  public static void main(String [] args) {\n" +
@@ -2326,9 +2265,6 @@
 				"}\n"
 			},
 			message,
-			null,
-			true,
-			new String[] { "--enable-preview"},
 			options);
 	}
 	public void testBug545518b() {
@@ -2381,9 +2317,7 @@
 				"     }\n"+
 				"}\n"
 		},
-		"5",
-		null,
-		new String[] {"--enable-preview"});
+		"5");
 	}
 	public void testBug545916_01() {
 		runConformTest(
@@ -2404,9 +2338,7 @@
 				"     }\n"+
 				"} \n"
 		},
-		"5",
-		null,
-		new String[] {"--enable-preview"});
+		"5");
 	}
 	public void testBug545983_01() {
 		this.runNegativeTest(
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 298ae13..91ba60c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -10630,7 +10630,7 @@
  * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=437639"
  */
 public void testBug437639() throws Exception {
-	this.formatterPrefs.blank_lines_between_import_groups = 0;
+	this.formatterPrefs.blank_lines_between_import_groups = ~0;
 	String source =
 		"package com.test;\n" +
 		"\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index 678c648..c76e787 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -14912,4 +14912,112 @@
 	String input = getCompilationUnit("Formatter", "", "test543818", "in.java").getSource();
 	formatSource(input, getCompilationUnit("Formatter", "", "test543818", "G_out.java").getSource());
 }
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249a() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_after_imports = ~2;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "A_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249b() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_after_package = ~1;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "B_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249c() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_at_beginning_of_method_body = ~0;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "C_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249d() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_field = ~3;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "D_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249e() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_first_class_body_declaration = ~2;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "E_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249f() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_imports = ~1;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "F_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249g() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_member_type = ~0;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "G_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249h() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_method = ~3;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "H_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249i() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_new_chunk = ~2;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "I_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249j() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_before_package = ~1;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "J_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249k() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_between_import_groups = ~1;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "K_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/549249 - [formatter] Extend Blank Lines settings to remove excess lines
+ */
+public void testBug549249l() throws JavaModelException {
+	this.formatterPrefs.number_of_empty_lines_to_preserve = 4;
+	this.formatterPrefs.blank_lines_between_type_declarations = ~3;
+	String input = getCompilationUnit("Formatter", "", "test549249", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test549249", "L_out.java").getSource());
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
index bd6a6e6..83eac08 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
@@ -104,6 +104,15 @@
 		return createSuite(ASTRewritingStatementsTest.class);
 	}
 
+ 	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		if (this.apiLevel >= AST.JLS12 ) {
+			this.project1.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
+			this.project1.setOption(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+		}
+	}
+	 	
 	/** @deprecated using deprecated code */
 	private void internalSetExtraDimensions(VariableDeclarationFragment node, int dimensions) {
 		if (this.apiLevel < AST.JLS8) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
index f10badf..e018cdd 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
@@ -17,6 +17,7 @@
 
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.Block;
@@ -53,6 +54,15 @@
 		return createSuite(ASTRewritingSwitchExpressionsTest.class);
 	}
 
+ 	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		if (this.apiLevel >= AST.JLS12 ) {
+			this.project1.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
+			this.project1.setOption(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+		}
+	}
+	 	
 	@SuppressWarnings("rawtypes")
 	public void testSwitchExpressions_since_12() throws Exception {
 		IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null);
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/A_out.java
new file mode 100644
index 0000000..99cf9d6
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/A_out.java
@@ -0,0 +1,105 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/B_out.java
new file mode 100644
index 0000000..d85ddc4
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/B_out.java
@@ -0,0 +1,104 @@
+
+
+
+
+package foo.bar.baz;
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/C_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/C_out.java
new file mode 100644
index 0000000..858e42a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/C_out.java
@@ -0,0 +1,95 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/D_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/D_out.java
new file mode 100644
index 0000000..8b1a855
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/D_out.java
@@ -0,0 +1,104 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+	private LinkedList fList;
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/E_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/E_out.java
new file mode 100644
index 0000000..64c13ca
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/E_out.java
@@ -0,0 +1,103 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/F_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/F_out.java
new file mode 100644
index 0000000..d85ddc4
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/F_out.java
@@ -0,0 +1,104 @@
+
+
+
+
+package foo.bar.baz;
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/G_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/G_out.java
new file mode 100644
index 0000000..3d0b9fe
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/G_out.java
@@ -0,0 +1,103 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/H_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/H_out.java
new file mode 100644
index 0000000..7ccb51d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/H_out.java
@@ -0,0 +1,104 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/I_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/I_out.java
new file mode 100644
index 0000000..2313207
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/I_out.java
@@ -0,0 +1,103 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/J_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/J_out.java
new file mode 100644
index 0000000..3e8b152
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/J_out.java
@@ -0,0 +1,104 @@
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/K_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/K_out.java
new file mode 100644
index 0000000..8d9484e
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/K_out.java
@@ -0,0 +1,101 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/L_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/L_out.java
new file mode 100644
index 0000000..70aed40
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/L_out.java
@@ -0,0 +1,106 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/in.java
new file mode 100644
index 0000000..c9e4c06
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549249/in.java
@@ -0,0 +1,107 @@
+
+
+
+
+package foo.bar.baz;
+
+
+
+
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+import org.eclipse.jdt.core.dom.ASTParser;
+
+
+
+
+import java.net.Socket;
+
+
+
+
+public class Another {
+}
+
+
+
+
+public class Example {
+
+
+
+
+	public class Nested {
+	}
+
+
+
+
+	public static class Pair {
+
+
+
+
+		public String first;
+
+
+
+
+		public String second;
+// Between here...
+
+
+
+
+// ...and here are 10 blank lines
+	};
+
+
+
+
+	private LinkedList fList;
+
+
+
+
+	public int counter;
+
+
+
+
+	public Example(LinkedList list) {
+
+
+
+
+		fList = list;
+		counter = 0;
+	}
+
+
+
+
+	public void push(Pair p) {
+
+
+
+
+		fList.add(p);
+		++counter;
+	}
+
+
+
+
+	public Object pop() {
+
+
+
+
+		--counter;
+		return (Pair) fList.getLast();
+	}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java
index b504b0b..1dcfc22 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java
@@ -95,7 +95,6 @@
 		return exp;
 	}
 
-	boolean isAutomodule;
 	private boolean isOpen = false;
 	char[] name;
 	IModule.IModuleReference[] requires;
@@ -154,7 +153,6 @@
 		} else {
 			this.opens = new PackageExportImpl[0];
 		}
-		this.isAutomodule = false; // Just to be explicit
 		this.isOpen = descriptor.isOpen();
 	}
 	@Override
@@ -186,10 +184,6 @@
 		return this.opens;
 	}
 	@Override
-	public boolean isAutomatic() {
-		return this.isAutomodule;
-	}
-	@Override
 	public boolean isOpen() {
 		return this.isOpen;
 	}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index ae30ebd..abccdea 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -398,9 +398,6 @@
 }
 @Override
 public IModule getModule() {
-	if (this.isAutoModule && this.module == null) {
-		return this.module = IModule.createAutomatic(this.path, false, null/*no manifest*/);
-	}
 	return this.module;
 }
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index c565187..0f85ef5 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -25,7 +25,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
-import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -330,18 +329,6 @@
 
 @Override
 public IModule getModule() {
-	if (this.isAutoModule && this.module == null) {
-		Manifest manifest = null;
-		try {
-			initialize();
-			ZipEntry entry = this.zipFile.getEntry(TypeConstants.META_INF_MANIFEST_MF);
-			if (entry != null)
-				manifest = new Manifest(this.zipFile.getInputStream(entry));
-		} catch (IOException e) {
-			// no usable manifest 
-		}
-		return this.module = IModule.createAutomatic(this.file.getName(), true, manifest);
-	}
 	return this.module;
 }
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
index f1e6a7e..ac693db 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
@@ -40,7 +40,6 @@
 	char[] normalizedPath;
 	public AccessRuleSet accessRuleSet;
 	IModule module;
-	protected boolean isAutoModule;
 
 	public String destinationPath;
 		// destination path for compilation units that are reached through this
@@ -126,11 +125,10 @@
 	@Override
 	public void acceptModule(IModule mod) {
 		this.module = mod;
-		this.isAutoModule = mod.isAutomatic();
 	}
 	@Override
 	public boolean isAutomaticModule() {
-		return this.isAutoModule;
+		return this.module == null ? false : this.module.isAutomatic();
 	}
 	@Override
 	public Collection<String> getModuleNames(Collection<String> limitModules) {
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 6c4a820..aa48467 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
@@ -147,7 +147,7 @@
 configure.differentencoding=Found encoding {0}. A different encoding was specified: {1}
 
 ### null annotations
-configure.invalidNullAnnot = Token {0} is not in the expected format "nullAnnot(<non null annotation name> | <nullable annotation name> | <non-null by default annotation name>)"
+configure.invalidNullAnnot = Token {0} is not in the expected format "nullAnnot(<nullable annotation name> | <non null annotation name> | <non-null by default annotation name>)"
 configure.missingAnnotationPath = Missing argument to -annotationpath at ''{0}''
 
 ### requestor
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index 50efb4c..9fab44d 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -4205,6 +4205,12 @@
 			} else if(parent instanceof InstanceOfExpression) {
 				InstanceOfExpression e = (InstanceOfExpression) parent;
 				TypeBinding binding = e.expression.resolvedType;
+				if (binding == null) {
+					if (scope instanceof BlockScope)
+						binding = e.expression.resolveType((BlockScope) scope);
+					else if (scope instanceof ClassScope)
+						binding = e.expression.resolveType((ClassScope) scope);
+				}
 				if(binding != null){
 					addExpectedType(binding, scope);
 					this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index f505570..76c76a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -95,6 +95,7 @@
 	public Expression expression;
 	public TypeReference type;
 	public TypeBinding expectedType; // when assignment conversion to a given expected type: String s = (String) t;
+	public TypeBinding instanceofType; // set by InstanceofExpression to ensure we don't flag a necessary cast unnecessary
 
 //{ObjectTeams: the following flags are set depending on the kind parameter of the constructor
 	/*  Should role types be wrapped?  */
@@ -763,6 +764,10 @@
 			boolean nullAnnotationMismatch = scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled
 					&& NullAnnotationMatching.analyse(castType, expressionType, -1).isAnyMismatch();
 
+			if (this.instanceofType != null && expressionType.isParameterizedType()
+					&& expressionType.isProvablyDistinct(this.instanceofType)) {
+				this.bits |= ASTNode.DisableUnnecessaryCastCheck;
+			}
 			boolean isLegal = checkCastTypesCompatibility(scope, castType, expressionType, this.expression);
 			if (isLegal) {
 				this.expression.computeConversion(scope, castType, expressionType);
@@ -860,6 +865,10 @@
 	this.bits |= ASTNode.UnnecessaryCast;
 }
 
+public void setInstanceofType(TypeBinding instanceofTypeBinding) {
+	this.instanceofType = instanceofTypeBinding;
+}
+
 @Override
 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index 7d500e5..7764774 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -193,7 +193,7 @@
 		for (int i = 0, max = this.localTypeCount; i < max; i++) {
 		    LocalTypeBinding localType = this.localTypes[i];
 			// null out the type's scope backpointers
-			localType.scope = null; // local members are already in the list
+			localType.cleanUp(); // local members are already in the list
 			localType.enclosingCase = null;
 		}
 	}
@@ -239,7 +239,7 @@
 		this.compilationResult.hasAnnotations = true;
 	if (type.binding != null) {
 		// null out the type's scope backpointers
-		type.binding.scope = null;
+		type.binding.cleanUp();
 	}
 //{ObjectTeams: final cleanup also from us:
 	type.cleanupModels();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index c5f10f2..c9505df 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -160,8 +160,11 @@
 @Override
 public TypeBinding resolveType(BlockScope scope) {
 	this.constant = Constant.NotAConstant;
-	TypeBinding expressionType = this.expression.resolveType(scope);
 	TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/);
+	if (this.expression instanceof CastExpression) {
+		((CastExpression) this.expression).setInstanceofType(checkedType); // for cast expression we need to know instanceof type to not tag unnecessary when needed
+	}
+	TypeBinding expressionType = this.expression.resolveType(scope);
 	if (expressionType != null && checkedType != null && this.type.hasNullTypeAnnotation(AnnotationPosition.ANY)) {
 		// don't complain if the entire operation is redundant anyway
 		if (!expressionType.isCompatibleWith(checkedType) || NullAnnotationMatching.analyse(checkedType, expressionType, -1).isAnyMismatch())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index 0d03db8..d6465cb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -59,11 +59,15 @@
 	this.synchroVariable.useFlag = LocalVariableBinding.USED;
 
 	// simple propagation to subnodes
+	FlowInfo expressionFlowInfo = this.expression.analyseCode(this.scope, flowContext, flowInfo);
+
+	this.expression.checkNPE(currentScope, flowContext, expressionFlowInfo, 1);
+
 	flowInfo =
 		this.block.analyseCode(
 			this.scope,
 			new InsideSubRoutineFlowContext(flowContext, this),
-			this.expression.analyseCode(this.scope, flowContext, flowInfo));
+			expressionFlowInfo);
 
 	this.mergedSynchronizedInitStateIndex =
 		currentScope.methodScope().recordInitializationStates(flowInfo);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 5fa2cd5..34b5c2a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -697,7 +697,7 @@
 	if ((tagBits & TagBits.AnnotationNonNull) != 0)
 		return NON_NULL;
 	if ((tagBits & TagBits.AnnotationNullable) != 0)
-		return POTENTIALLY_NULL | POTENTIALLY_NON_NULL;
+		return POTENTIALLY_NULL;
 	return UNKNOWN;
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index 9038b44..2c1023a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -1412,7 +1412,7 @@
 	}
 }
 private boolean checkAppropriate(MethodBinding compileTimeDeclaration, MethodBinding otherMethod, InvocationSite location) {
-	if (otherMethod == null || !otherMethod.isValidBinding() || otherMethod == compileTimeDeclaration)
+	if (otherMethod == null || !otherMethod.isValidBinding() || otherMethod.original() == compileTimeDeclaration.original())
 		return true;
 	if (MethodVerifier.doesMethodOverride(otherMethod, compileTimeDeclaration, this.environment())) {
 		problemReporter().illegalSuperCallBypassingOverride(location, compileTimeDeclaration, otherMethod.declaringClass);
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 2db7c5a..78cff89 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
@@ -102,7 +102,7 @@
 		}
 		// pre: this.subBounds != null
 		public TypeBinding[] upperBounds(boolean onlyProper, InferenceVariable variable) {
-			ReferenceBinding[] rights = new ReferenceBinding[this.subBounds.size()];
+			TypeBinding[] rights = new TypeBinding[this.subBounds.size()];
 			TypeBinding simpleUpper = null;
 			Iterator<TypeBound> it = this.subBounds.iterator();
 			long nullHints = variable.nullHints;
@@ -111,7 +111,7 @@
 				TypeBinding right=it.next().right;
 				if (!onlyProper || right.isProperType(true)) {
 					if (right instanceof ReferenceBinding) {
-						rights[i++] = (ReferenceBinding) right;
+						rights[i++] = right;
 						nullHints |= right.tagBits & TagBits.AnnotationNullMASK; 
 					} else {
 						if (simpleUpper != null)
@@ -125,7 +125,7 @@
 			if (i == 1 && simpleUpper != null)
 				return new TypeBinding[] { simpleUpper }; // no nullHints since not a reference type
 			if (i < rights.length)
-				System.arraycopy(rights, 0, rights=new ReferenceBinding[i], 0, i);
+				System.arraycopy(rights, 0, rights=new TypeBinding[i], 0, i);
 			useNullHints(nullHints, rights, variable.environment);
 			InferenceContext18.sortTypes(rights);
 			return rights;
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 4957f3e..f2a76ad 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
@@ -1169,18 +1169,18 @@
 										if (upperBounds.length == 1) {
 											glb = upperBounds[0];
 										} else {
-											ReferenceBinding[] glbs = Scope.greaterLowerBound((ReferenceBinding[])upperBounds);
+											TypeBinding[] glbs = Scope.greaterLowerBound(upperBounds, this.scope, this.environment);
 											if (glbs == null) {
 												return null;
 											} else if (glbs.length == 1) {
 												glb = glbs[0];
 											} else {
-												IntersectionTypeBinding18 intersection = (IntersectionTypeBinding18) this.environment.createIntersectionType18(glbs);
-												if (!ReferenceBinding.isConsistentIntersection(intersection.intersectingTypes)) {
+												glb = intersectionFromGlb(glbs);
+												if (glb == null) {
+													// inconsistent intersection
 													tmpBoundSet = prevBoundSet; // clean up
-													break variables; // and start over
+													break variables; // and start over													
 												}
-												glb = intersection;
 											}
 										}
 									}
@@ -1280,6 +1280,22 @@
 		return tmpBoundSet;
 	}
 	
+	private TypeBinding intersectionFromGlb(TypeBinding[] glbs) {
+		ReferenceBinding[] refGlbs = new ReferenceBinding[glbs.length];
+		for (int i = 0; i < glbs.length; i++) {
+			TypeBinding typeBinding = glbs[i];
+			if (typeBinding instanceof ReferenceBinding) {
+				refGlbs[i] = (ReferenceBinding) typeBinding;
+			} else {
+				return null;
+			}
+		}
+		IntersectionTypeBinding18 intersection = (IntersectionTypeBinding18) this.environment.createIntersectionType18(refGlbs);
+		if (ReferenceBinding.isConsistentIntersection(intersection.intersectingTypes))
+			return intersection;
+		return null;
+	}
+	
 	int captureId = 0;
 	
 	/** For 18.4: "Let Z1, ..., Zn be fresh type variables" use capture bindings. */
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 e90c7dd..44ea255 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
@@ -243,7 +243,7 @@
 	this.typeVariables = prototype.typeVariables;
 	this.environment = prototype.environment;
 
-	// this.scope = prototype.scope;  // Will defeat CompilationUnitDeclaration.cleanUp(TypeDeclaration) && CompilationUnitDeclaration.cleanUp(), so not copied, not an issue for JSR 308.
+	this.scope = prototype.scope; // compensated by TypeSystem.cleanUp(int)
 
 	this.synthetics = prototype.synthetics;
 	this.genericReferenceTypeSignature = prototype.genericReferenceTypeSignature;
@@ -3751,4 +3751,12 @@
 	return list;
 }
 
+public void cleanUp() {
+	if (this.environment != null) {
+		// delegate so as to clean all variants of this prototype:
+		this.environment.typeSystem.cleanUp(this.id);
+	}
+	this.scope = null; // for types that are not registered in typeSystem.
+}
+
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
index abb522b..4d26fd5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2018 IBM Corporation and others.
+ * Copyright (c) 2013, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -647,6 +647,17 @@
 		return false;
 	}
 
+	public void cleanUp(int typeId) {
+		if (typeId != -1 && typeId < this.typeid && this.types != null) {
+			TypeBinding[] typesForId = this.types[typeId];
+			if (typesForId != null) {
+				for (TypeBinding type : typesForId)
+					if (type instanceof SourceTypeBinding)
+						((SourceTypeBinding) type).scope = null;
+			}
+		}
+	}
+
 	public void reset() {
 		this.annotationTypes = new SimpleLookupTable(16);
 		this.typeid = TypeIds.T_LastWellKnownTypeId;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index b3d3900..1216958 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -553,9 +553,11 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_UNION_TYPE_IN_MULTICATCH = JavaCore.PLUGIN_ID + ".formatter.alignment_for_union_type_in_multicatch";	 //$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines after the imports declaration
+	 * FORMATTER / Option to add or remove blank lines after the imports declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_after_imports"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -563,9 +565,11 @@
 	public static final String FORMATTER_BLANK_LINES_AFTER_IMPORTS = JavaCore.PLUGIN_ID + ".formatter.blank_lines_after_imports";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines after the package declaration
+	 * FORMATTER / Option to add or remove blank lines after the package declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_after_package"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -573,9 +577,11 @@
 	public static final String FORMATTER_BLANK_LINES_AFTER_PACKAGE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_after_package";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines at the beginning of the method body
+	 * FORMATTER / Option to add or remove blank lines at the beginning of the method body
 	 *     - option id:         "org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -583,9 +589,11 @@
 	public static final String FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY = JavaCore.PLUGIN_ID + ".formatter.number_of_blank_lines_at_beginning_of_method_body"; //$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before a field declaration
+	 * FORMATTER / Option to add or remove blank lines before a field declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_field"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -593,9 +601,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_FIELD = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_field";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before the first class body declaration
+	 * FORMATTER / Option to add or remove blank lines before the first class body declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -603,9 +613,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_first_class_body_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before the imports declaration
+	 * FORMATTER / Option to add or remove blank lines before the imports declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_imports"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -613,9 +625,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_IMPORTS = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_imports";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before a member type declaration
+	 * FORMATTER / Option to add or remove blank lines before a member type declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_member_type"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -623,9 +637,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_member_type";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before a method declaration
+	 * FORMATTER / Option to add or remove blank lines before a method declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_method"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -633,9 +649,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_METHOD = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_method";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before a new chunk
+	 * FORMATTER / Option to add or remove blank lines before a new chunk
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -643,9 +661,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_new_chunk";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines before the package declaration
+	 * FORMATTER / Option to add or remove blank lines before the package declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_before_package"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
@@ -653,9 +673,11 @@
 	public static final String FORMATTER_BLANK_LINES_BEFORE_PACKAGE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_package";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines between import groups
+	 * FORMATTER / Option to add or remove blank lines between import groups
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_between_import_groups"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "1"
 	 * </pre>
 	 * Note: Import groups are defined once "Organize Import" operation has been executed. The code formatter itself
@@ -666,9 +688,11 @@
 	public static final String FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS = JavaCore.PLUGIN_ID + ".formatter.blank_lines_between_import_groups";	//$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to add blank lines between type declarations
+	 * FORMATTER / Option to add or remove blank lines between type declarations
 	 *     - option id:         "org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations"
-	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
+	 *     - possible values:   "&lt;n&gt;", where n is an integer. If n is negative, the actual number of
+	 *                          blank lines is ~n and any excess blank lines are deleted, overriding the
+	 *                          {@link #FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE} option
 	 *     - default:           "0"
 	 * </pre>
 	 * @since 3.0
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
index 3e61b06..913d86f 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
@@ -25,7 +25,6 @@
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamebase;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameelse;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamefinally;
-import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamepackage;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhen;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhile;
 
@@ -104,10 +103,18 @@
 	@Override
 	public boolean visit(CompilationUnit node) {
 		List<ImportDeclaration> imports = node.imports();
-		if (!imports.isEmpty()) {
-			int index = this.tm.firstIndexIn(imports.get(0), -1);
-			if (index > 0)
-				this.tm.get(index).putLineBreaksBefore(this.options.blank_lines_before_imports + 1);
+		if (!imports.isEmpty() && this.tm.firstIndexIn(imports.get(0), -1) > 0)
+			putBlankLinesBefore(imports.get(0), this.options.blank_lines_before_imports);
+
+		for (int i = 1; i < imports.size(); i++) {
+			int from = this.tm.lastIndexIn(imports.get(i - 1), -1);
+			int to = this.tm.firstIndexIn(imports.get(i), -1);
+			for (int j = from; j < to; j++) {
+				Token token1 = this.tm.get(j);
+				Token token2 = this.tm.get(j + 1);
+				if (this.tm.countLineBreaksBetween(token1, token2) > 1)
+					putBlankLinesAfter(token1, this.options.blank_lines_between_import_groups);
+			}
 		}
 
 		List<AnnotationTypeDeclaration> types = node.types();
@@ -122,14 +129,13 @@
 
 	@Override
 	public boolean visit(PackageDeclaration node) {
-		int blanks = this.options.blank_lines_before_package;
-		if (blanks > 0) {
-			List<Annotation> annotations = node.annotations();
-			int firstTokenIndex = annotations.isEmpty() ? this.tm.firstIndexBefore(node.getName(), TokenNamepackage)
-					: this.tm.firstIndexIn(annotations.get(0), -1);
-			this.tm.get(firstTokenIndex).putLineBreaksBefore(blanks + 1);
+		if (node.getJavadoc() == null) {
+			putBlankLinesBefore(node, this.options.blank_lines_before_package);
+		} else {
+			putBlankLinesAfter(this.tm.lastTokenIn(node.getJavadoc(), -1), this.options.blank_lines_before_package);
 		}
-		this.tm.lastTokenIn(node, TokenNameSEMICOLON).putLineBreaksAfter(this.options.blank_lines_after_package + 1);
+
+		putBlankLinesAfter(this.tm.lastTokenIn(node, -1), this.options.blank_lines_after_package);
 		this.declarationModifierVisited = false;
 		return true;
 	}
@@ -185,10 +191,9 @@
 // SH}
 				}
 
-				if (!sameChunk(previous, bodyDeclaration))
-					blankLines = Math.max(blankLines, this.options.blank_lines_before_new_chunk);
-
 				putBlankLinesBefore(bodyDeclaration, blankLines);
+				if (!sameChunk(previous, bodyDeclaration))
+					putBlankLinesBefore(bodyDeclaration, this.options.blank_lines_before_new_chunk);
 			}
 			previous = bodyDeclaration;
 		}
@@ -209,7 +214,21 @@
 		int index = this.tm.firstIndexIn(node, -1);
 		while (index > 0 && this.tm.get(index - 1).tokenType == TokenNameCOMMENT_JAVADOC)
 			index--;
-		this.tm.get(index).putLineBreaksBefore(linesCount + 1);
+		if (linesCount >= 0) {
+			this.tm.get(index).putLineBreaksBefore(linesCount + 1);
+		} else {
+			this.tm.get(index).putLineBreaksBefore(~linesCount + 1);
+			this.tm.get(index).setPreserveLineBreaksBefore(false);
+		}
+	}
+
+	private void putBlankLinesAfter(Token token, int linesCount) {
+		if (linesCount >= 0) {
+			token.putLineBreaksAfter(linesCount + 1);
+		} else {
+			token.putLineBreaksAfter(~linesCount + 1);
+			token.setPreserveLineBreaksAfter(false);
+		}
 	}
 
 	@Override
@@ -281,7 +300,7 @@
 		handleBracedCode(node.getBody(), null, bracePosition, this.options.indent_statements_compare_to_body);
 		Token openBrace = this.tm.firstTokenIn(node.getBody(), TokenNameLBRACE);
 		if (openBrace.getLineBreaksAfter() > 0) // if not, these are empty braces
-			openBrace.putLineBreaksAfter(this.options.blank_lines_at_beginning_of_method_body + 1);
+			putBlankLinesAfter(openBrace, this.options.blank_lines_at_beginning_of_method_body);
 		return true;
 	}
 
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
index 18ee94d..b2b7144 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
@@ -97,6 +97,7 @@
 	public final int tokenType;
 	private boolean spaceBefore, spaceAfter;
 	private int lineBreaksBefore, lineBreaksAfter;
+	private boolean preserveLineBreaksBefore = true, preserveLineBreaksAfter = true;
 	private boolean wrapped;
 	private int indent;
 	private int emptyLineIndentAdjustment;
@@ -129,6 +130,8 @@
 		this.spaceAfter = tokenToCopy.spaceAfter;
 		this.lineBreaksBefore = tokenToCopy.lineBreaksBefore;
 		this.lineBreaksAfter = tokenToCopy.lineBreaksAfter;
+		this.preserveLineBreaksBefore = tokenToCopy.preserveLineBreaksBefore;
+		this.preserveLineBreaksAfter = tokenToCopy.preserveLineBreaksAfter;
 		this.indent = tokenToCopy.indent;
 		this.nextLineOnWrap = tokenToCopy.nextLineOnWrap;
 		this.wrapPolicy = tokenToCopy.wrapPolicy;
@@ -217,6 +220,22 @@
 		this.lineBreaksAfter = 0;
 	}
 
+	public void setPreserveLineBreaksBefore(boolean preserveLineBreaksBefore) {
+		this.preserveLineBreaksBefore = preserveLineBreaksBefore;
+	}
+
+	public boolean isPreserveLineBreaksBefore() {
+		return this.preserveLineBreaksBefore;
+	}
+
+	public void setPreserveLineBreaksAfter(boolean preserveLineBreaksAfter) {
+		this.preserveLineBreaksAfter = preserveLineBreaksAfter;
+	}
+
+	public boolean isPreserveLineBreaksAfter() {
+		return this.preserveLineBreaksAfter;
+	}
+
 	/** Increases this token's indentation by one position */
 	public void indent() {
 		this.indent++;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
index 011565e..79962ab 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
@@ -204,17 +204,21 @@
 	private boolean isNewGroup(ASTNode node, ASTNode previousNode) {
 		if (previousNode == null)
 			return true;
-		int lineBreaks = 0;
+		int totalLineBreaks = 0;
 		int from = this.tm.lastIndexIn(previousNode, -1);
 		int to = this.tm.firstIndexIn(node, -1);
 		Token previousToken = this.tm.get(from);
 		for (int i = from + 1; i <= to; i++) {
 			Token token = this.tm.get(i);
-			lineBreaks += Math.min(this.tm.countLineBreaksBetween(previousToken, token),
-					this.options.number_of_empty_lines_to_preserve + 1);
+			int lineBreaks = Math.max(previousToken.getLineBreaksAfter(), token.getLineBreaksBefore());
+			if (previousToken.isPreserveLineBreaksAfter() && token.isPreserveLineBreaksBefore()) {
+				lineBreaks = Math.max(lineBreaks, Math.min(this.tm.countLineBreaksBetween(previousToken, token),
+						this.options.number_of_empty_lines_to_preserve + 1));
+			}
+			totalLineBreaks += lineBreaks;
 			previousToken = token;
 		}
-		return lineBreaks > this.options.align_fields_grouping_blank_lines;
+		return totalLineBreaks > this.options.align_fields_grouping_blank_lines;
 	}
 
 	private <N extends ASTNode> void alignNodes(List<N> alignGroup, AlignIndexFinder<N> tokenFinder) {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index b61187a..678cc88 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -62,7 +62,6 @@
 import org.eclipse.jdt.core.dom.Block;
 import org.eclipse.jdt.core.dom.CatchClause;
 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
-import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.ConditionalExpression;
 import org.eclipse.jdt.core.dom.ConstructorInvocation;
 import org.eclipse.jdt.core.dom.CreationReference;
@@ -77,7 +76,6 @@
 import org.eclipse.jdt.core.dom.FieldDeclaration;
 import org.eclipse.jdt.core.dom.ForStatement;
 import org.eclipse.jdt.core.dom.IfStatement;
-import org.eclipse.jdt.core.dom.ImportDeclaration;
 import org.eclipse.jdt.core.dom.InfixExpression;
 import org.eclipse.jdt.core.dom.InfixExpression.Operator;
 import org.eclipse.jdt.core.dom.LambdaExpression;
@@ -229,8 +227,6 @@
 
 	final Aligner aligner;
 
-	int importsStart = -1, importsEnd = -1;
-
 	/*
 	 * temporary values used when calling {@link #handleWrap(int)} to avoid ArrayList initialization and long lists of
 	 * parameters
@@ -272,16 +268,6 @@
 	}
 
 	@Override
-	public boolean visit(CompilationUnit node) {
-		List<ImportDeclaration> imports = node.imports();
-		if (!imports.isEmpty()) {
-			this.importsStart = this.tm.firstIndexIn(imports.get(0), -1);
-			this.importsEnd = this.tm.lastIndexIn(imports.get(imports.size() - 1), -1);
-		}
-		return true;
-	}
-
-	@Override
 	public boolean visit(NormalAnnotation node) {
 		int lParen = this.tm.firstIndexAfter(node.getTypeName(), TokenNameLPAREN);
 		int rParen = this.tm.lastIndexIn(node, TokenNameRPAREN);
@@ -1353,9 +1339,7 @@
 
 			@Override
 			protected boolean token(Token token, int index) {
-				boolean isBetweenImports = index > WrapPreparator.this.importsStart
-						&& index < WrapPreparator.this.importsEnd;
-				int lineBreaks = getLineBreaksToPreserve(getPrevious(), token, isBetweenImports);
+				int lineBreaks = getLineBreaksToPreserve(getPrevious(), token);
 				if (lineBreaks > 1 || (!this.join_wrapped_lines && token.isWrappable()) || index == 0)
 					token.putLineBreaksBefore(lineBreaks);
 				return true;
@@ -1365,7 +1349,7 @@
 
 		Token last = this.tm.get(this.tm.size() - 1);
 		last.clearLineBreaksAfter();
-		int endingBreaks = getLineBreaksToPreserve(last, null, false);
+		int endingBreaks = getLineBreaksToPreserve(last, null);
 		if (endingBreaks > 0) {
 			last.putLineBreaksAfter(endingBreaks);
 		} else if ((this.kind & (CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.K_MODULE_INFO)) != 0
@@ -1374,7 +1358,11 @@
 		}
 	}
 
-	int getLineBreaksToPreserve(Token token1, Token token2, boolean isBetweenImports) {
+	int getLineBreaksToPreserve(Token token1, Token token2) {
+		if ((token1 != null && !token1.isPreserveLineBreaksAfter())
+				|| (token2 != null && !token2.isPreserveLineBreaksBefore())) {
+			return 0;
+		}
 		if (token1 != null) {
 			List<Token> structure = token1.getInternalStructure();
 			if (structure != null && !structure.isEmpty())
@@ -1386,9 +1374,6 @@
 				token2 = structure.get(0);
 		}
 		int lineBreaks = WrapPreparator.this.tm.countLineBreaksBetween(token1, token2);
-		if (isBetweenImports)
-			return lineBreaks > 1 ? (this.options.blank_lines_between_import_groups + 1) : 0;
-
 		int toPreserve = this.options.number_of_empty_lines_to_preserve;
 		if (token1 != null && token2 != null)
 			toPreserve++; // n empty lines = n+1 line breaks, except for file start and end
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 623f116..012a927 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -39,6 +39,7 @@
 
 public class ClasspathDirectory extends ClasspathLocation {
 
+final boolean isOnModulePath;
 IContainer binaryFolder; // includes .class files for a single directory
 boolean isOutputFolder;
 SimpleLookupTable directoryCache;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 449469a..ca01706 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -48,6 +48,7 @@
 
 @SuppressWarnings("rawtypes")
 public class ClasspathJar extends ClasspathLocation {
+final boolean isOnModulePath;
 
 static class PackageCacheEntry {
 	long lastModified;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 891aede..436922d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -38,7 +38,6 @@
 
 public abstract class ClasspathLocation {
 
-	protected boolean isOnModulePath;
 	protected IModule module;
 	protected IUpdatableModule.UpdatesByKind updates;
 	protected Set<String> limitModuleNames = null;
@@ -134,13 +133,13 @@
 										long lastModified, 
 										AccessRuleSet accessRuleSet, 
 										IPath annotationsPath,
-										boolean autoModule,
+										boolean isOnModulePath,
 										String compliance) {
 	return Util.archiveFormat(libraryPathname) == Util.JMOD_FILE ?
 					new ClasspathJMod(libraryPathname, lastModified, accessRuleSet, annotationsPath) :
 						(compliance == null || (CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK9) ?
-			new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule) :
-				new ClasspathMultiReleaseJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule, compliance));
+			new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, isOnModulePath) :
+				new ClasspathMultiReleaseJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, isOnModulePath, compliance));
 
 }
 public static ClasspathJrt forJrtSystem(String jrtPath, AccessRuleSet accessRuleSet, IPath annotationsPath, String release) throws CoreException {
@@ -149,15 +148,15 @@
 }
 
 public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath,
-											boolean autoModule, String compliance) {
-	return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath, autoModule, compliance);
+											boolean isOnModulePath, String compliance) {
+	return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath, isOnModulePath, compliance);
 }
 
 static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath,
-										boolean autoModule, String compliance) {
+										boolean isOnModulePath, String compliance) {
 	return (CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK9) ?
-			new ClasspathJar(library, accessRuleSet, annotationsPath, autoModule) :
-				new ClasspathMultiReleaseJar(library, accessRuleSet, annotationsPath, autoModule, compliance);
+			new ClasspathJar(library, accessRuleSet, annotationsPath, isOnModulePath) :
+				new ClasspathMultiReleaseJar(library, accessRuleSet, annotationsPath, isOnModulePath, compliance);
 }
 public static ClasspathLocation forLibrary(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
 	return (CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK9) ?
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index a760438..35b85e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -50,6 +50,13 @@
 public static boolean SHOW_STATS = false;
 
 /**
+ * Bug 549457: In case auto-building on a JDT core settings change (e.g. compiler compliance) is not desired,
+ * specify VM property: {@code -Dorg.eclipse.jdt.core.disableAutoBuildOnSettingsChange=true}
+ */
+private static final boolean DISABLE_AUTO_BUILDING_ON_SETTINGS_CHANGE = Boolean.getBoolean("org.eclipse.jdt.core.disableAutoBuildOnSettingsChange"); //$NON-NLS-1$
+private static final IPath JDT_CORE_SETTINGS_PATH = Path.fromPortableString(JavaProject.DEFAULT_PREFERENCES_DIRNAME + IPath.SEPARATOR + JavaProject.JAVA_CORE_PREFS_FILE);
+
+/**
  * A list of project names that have been built.
  * This list is used to reset the JavaModel.existingExternalFiles cache when a build cycle begins
  * so that deleted external jars are discovered.
@@ -200,7 +207,13 @@
 							System.out.println("JavaBuilder: Performing full build since deltas are missing after incremental request"); //$NON-NLS-1$
 						buildAll();
 					} else if (deltas.elementSize > 0) {
-						buildDeltas(deltas);
+						if (hasJdtCoreSettingsChange(deltas) && !DISABLE_AUTO_BUILDING_ON_SETTINGS_CHANGE) {
+							if (DEBUG)
+								System.out.println("JavaBuilder: Performing full build since project settings have changed"); //$NON-NLS-1$
+							buildAll();
+						} else {
+							buildDeltas(deltas);
+						}
 					} else if (DEBUG) {
 						System.out.println("JavaBuilder: Nothing to build since deltas were empty"); //$NON-NLS-1$
 					}
@@ -516,6 +529,42 @@
 	return false;
 }
 
+private boolean hasJdtCoreSettingsChange(SimpleLookupTable deltas) {
+	Object resourceDelta = deltas.get(this.currentProject);
+	if (resourceDelta instanceof IResourceDelta) {
+		IResourceDelta delta = (IResourceDelta) resourceDelta;
+		class CheckForJdtCoreSettingsFileChange implements IResourceDeltaVisitor {
+
+			boolean hasJdtCoreSettingsChange = false;
+
+			@Override
+			public boolean visit(IResourceDelta childDelta) throws CoreException {
+				IResource resource = childDelta.getResource();
+				boolean isJdtCoreSettingsResource = isJdtCoreSettingsResource(resource);
+				if (isJdtCoreSettingsResource) {
+					this.hasJdtCoreSettingsChange = true;
+					return false; // stop visiting, the JDT core settings file changed
+				}
+				return true;
+			}
+		}
+		try {
+			CheckForJdtCoreSettingsFileChange visitor = new CheckForJdtCoreSettingsFileChange();
+			delta.accept(visitor);
+			return visitor.hasJdtCoreSettingsChange;
+		} catch (CoreException e) {
+			Util.log(e, "Failed to check whether deltas contain JDT preference changes"); //$NON-NLS-1$
+		}
+	}
+	return false;
+}
+
+static boolean isJdtCoreSettingsResource(IResource resource) {
+	IPath resourcePath = resource.getProjectRelativePath();
+	boolean isJdtCoreSettingsResource = JDT_CORE_SETTINGS_PATH.equals(resourcePath);
+	return isJdtCoreSettingsResource;
+}
+
 private boolean hasClasspathChanged() {
 	return hasClasspathChanged(CompilationGroup.MAIN) || hasClasspathChanged(CompilationGroup.TEST);	
 }