update jdt.core to I20190705-1800
diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
index 07fbadc..a995ac1 100644
--- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.12.900.qualifier
+Bundle-Version: 3.12.950.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.core.tests.compiler,
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index d8ca749..a76daab 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -15,12 +15,12 @@
   <parent>
     <artifactId>tests-pom</artifactId>
     <groupId>eclipse.jdt.core</groupId>
-    <version>4.12.0-SNAPSHOT</version>
+    <version>4.13.0-SNAPSHOT</version>
     <relativePath>../tests-pom/</relativePath>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
-  <version>3.12.900-SNAPSHOT</version>
+  <version>3.12.950-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index f2bea4d..53e2dd5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -744,6 +744,7 @@
         "                       do not stop at first error, dumping class files with\n" + 
         "                       problem methods\n" + 
         "                       With \":Fatal\", all optional errors are treated as fatal\n" + 
+        "    -failOnWarning     fail compilation if there are warnings\n" +
         "    -verbose           enable verbose output\n" +
         "    -referenceInfo     compute reference info\n" +
         "    -progress          show progress (only in -log mode)\n" +
@@ -13213,4 +13214,46 @@
 		"",
 		false);
 }
+
+public void testFailOnWarnings_NoWarning() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"/** */\n" +
+			"public class X {\n" +
+			"}",
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+		+ " -failOnWarning"
+		+ " -d \"" + OUTPUT_DIR + File.separator + "bin/\"",
+		"",
+		"",
+		true);
+	
+}
+
+public void testFailOnWarnings_WithWarning() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"/** */\n" +
+			"public class X {\n" +
+			"private int a;\n" +		
+			"}",
+		},
+		"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+		+ " -failOnWarning"
+		+ " -d \"" + OUTPUT_DIR + File.separator + "bin/\"",
+		"",
+		"----------\n" + 
+		"1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 3)\n" + 
+		"	private int a;\n" + 
+		"	            ^\n" + 
+		"The value of the field X.a is not used\n" + 
+		"----------\n" + 
+		"1 problem (1 warning)\n" + 
+		"error: warnings found and -failOnWarning specified\n" + 
+		"",
+		true);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index 2becc1c..1abf4f9 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -9906,4 +9906,53 @@
 				"}\n"
 			});
 	}
+	public void testBug547807() {
+		runConformTest(
+			new String[] {
+				"DslStep1.java",
+				"public interface DslStep1 {\n" + 
+				"	DslStep2<?> nextStep();\n" + 
+				"}\n",
+				"DslStep2.java",
+				"public interface DslStep2<S extends DslStep2<? extends S>> {\n" + 
+				"	S doSomething();\n" + 
+				"}\n",
+				"CallBug.java",
+				"public class CallBug {\n" + 
+				"	public void doesNotCompileWithEcj(DslStep1 step1) {\n" + 
+				"		// Note we need three chained calls for the problem to show up. Two is not enough.\n" + 
+				"		step1.nextStep().doSomething().doSomething().doSomething();\n" + 
+				"	}\n" + 
+				"}\n"
+			});
+	}
+	public void testBug548589() {
+		runConformTest(
+			new String[] {
+				"InferenceCheck.java",
+				"import java.util.*;\n" + 
+				"import java.util.function.*;\n" + 
+				"\n" + 
+				"public class InferenceCheck {\n" + 
+				"\n" + 
+				"    public interface P<T> {\n" + 
+				"\n" + 
+				"        public boolean apply(T value);        \n" + 
+				"    }\n" + 
+				"\n" + 
+				"    public static <T> P<T> compilation_failed(P<T> predicate) {\n" + 
+				"        List<P<T>> list = Collections.emptyList();\n" + 
+				"        list.stream().map(InferenceCheck::compilation_failed);\n" + 
+				"        return null;\n" + 
+				"    }    \n" + 
+				"\n" + 
+				"    public static <T> P<T> compilation_ok(P<T> predicate) {\n" + 
+				"        List<P<T>> list = Collections.emptyList();\n" + 
+				"        Function<P<T>, P<T>> f = InferenceCheck::compilation_ok;\n" + 
+				"        list.stream().map(f);\n" + 
+				"        return null;\n" + 
+				"    }    \n" + 
+				"}\n"
+			});
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
index c329fba..8464c36 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
@@ -71,8 +71,13 @@
 	}
 
 	@Override
-	public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
-		return collect(env -> env.getModulesDeclaringPackage(parentPackageName, name, moduleName), char[][]::new);
+	public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+		return collect(env -> env.getModulesDeclaringPackage(packageName, moduleName), char[][]::new);
+	}
+
+	@Override
+	public char[][] listPackages(char[] moduleName) {
+		return collect(env -> env.listPackages(moduleName), char[][]::new);
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index bd58503..83fb845 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -31,8 +31,14 @@
 import java.util.Set;
 
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.core.util.IClassFileAttribute;
+import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.core.util.IModuleAttribute;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
@@ -1080,8 +1086,8 @@
 				"----------\n" +
 				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 3)\n" +
 				"	java.sql.Connection con = p.X.getConnection();\n" +
-				"	                          ^\n" +
-				"p cannot be resolved\n" +
+				"	                          ^^^\n" +
+				"The type p.X is not accessible\n" +
 				"----------\n" +
 				"1 problem (1 error)\n",
 				false,
@@ -5314,4 +5320,129 @@
 				false,
 				"unnamed package is not allowed in named modules");
 	}
+	public void testBug548195() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+
+		StringBuffer buffer = new StringBuffer();
+		String binDir = OUTPUT_DIR + File.separator + out;
+		buffer.append("-d " + binDir )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" -warn:-unused")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(" --module-version 47.11 ");
+		String outText = isJRE9Plus ? "" : "Could not invoke method java.lang.module.ModuleDescriptor.Version.parse(), cannot validate module version.\n";
+		runConformModuleTest(files, buffer, outText, "", false);
+
+		IClassFileReader cfr = ToolFactory.createDefaultClassFileReader(binDir + File.separator + "mod.one" + File.separator + "module-info.class", IClassFileReader.CLASSFILE_ATTRIBUTES);
+		assertNotNull("Error reading module-info.class", cfr);
+		IClassFileAttribute[] attrs = cfr.getAttributes();
+		for (IClassFileAttribute attr : attrs) {
+			char[] name = attr.getAttributeName();
+			if (CharOperation.equals(name, AttributeNamesConstants.ModuleName)) {
+				IModuleAttribute modAttr = (IModuleAttribute) attr;
+				String expectedVersion = isJRE9Plus ? "47.11" : "";
+				assertEquals("version in attribute", expectedVersion, new String(modAttr.getModuleVersionValue()));
+				return;
+			}
+		}
+		fail("module attribute not found");
+	}
+	public void testBug548195fail() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+
+		StringBuffer buffer = new StringBuffer();
+		String binDir = OUTPUT_DIR + File.separator + out;
+		buffer.append("-d " + binDir )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" -warn:-unused")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(" --module-version fourtyseven.11 ");
+		if (isJRE9Plus) {
+			runNegativeModuleTest(files, buffer, "", "fourtyseven.11: Version string does not start with a number\n", false, "bad value");			
+		} else {
+			runConformModuleTest(files, buffer, "Could not invoke method java.lang.module.ModuleDescriptor.Version.parse(), cannot validate module version.\n", "", false);
+		}
+	}
+	public void testPackageTypeConflict2() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+								"	exports p1.p2;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p1" + File.separator + "p2", "t3.java", 
+						"package p1.p2;\n" +
+						"public class t3 {\n" +
+						"}\n");
+
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+							"	exports p1.p2.t3;\n" +
+							"	requires mod.one;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p1" + File.separator + "p2" + File.separator + "t3", "t4.java", 
+						"package p1.p2.t3;\n" +
+						"public class t4 {\n" +
+						"}\n");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+
+		runNegativeModuleTest(
+				files,
+				buffer,
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p1/p2/t3/t4.java (at line 1)\n" + 
+				"	package p1.p2.t3;\n" + 
+				"	        ^^^^^^^^\n" + 
+				"The package p1.p2.t3 collides with a type\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false,
+				"package p1.p2.t3 clashes with class of same name");
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
index b8e7a88..61a6e06 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
 import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
 
 public class PackageBindingTest extends AbstractCompilerTest
@@ -36,7 +37,7 @@
 	public void _test01() {
 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(true);
 
-		PackageBinding packageBinding = new PackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
+		PlainPackageBinding packageBinding = new PlainPackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
 		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null, false);
 		assertNotNull(resultBinding);
 
@@ -53,7 +54,7 @@
 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(false);
 
 		LookupEnvironment environment = new LookupEnvironment(null, new CompilerOptions(), null, nameEnv);
-		PackageBinding packageBinding = new PackageBinding(environment);
+		PlainPackageBinding packageBinding = new PlainPackageBinding(environment);
 		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), environment.module, false);
 		assertNull(resultBinding); // (not implemented)
 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationSetup.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationSetup.java
index 1e4651e..74f1dcf 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationSetup.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationSetup.java
@@ -18,6 +18,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.ServerSocket;
+import java.time.Duration;
+import java.time.Instant;
 import java.util.List;
 import java.util.Map;
 
@@ -59,31 +61,33 @@
 					launcher.setDebugPort(debugPort);
 					this.launchedVM = launcher.launch();
 				} catch (TargetException e) {
-					e.printStackTrace();
+					e.printStackTrace(System.out);
 					throw new Error(e.getMessage(), e);
 				}
-	
+
 				// Thread that read the stout of the VM so that the VM doesn't block
 				try {
 					startReader("VM's stdout reader", this.launchedVM.getInputStream(), System.out);
 				} catch (TargetException e) {
-					e.printStackTrace();
+					e.printStackTrace(System.out);
 				}
-	
+
 				// Thread that read the sterr of the VM so that the VM doesn't block
 				try {
-					startReader("VM's sterr reader", this.launchedVM.getErrorStream(), System.err);
+					startReader("VM's sterr reader", this.launchedVM.getErrorStream(), System.out);
 				} catch (TargetException e) {
-					e.printStackTrace();
+					e.printStackTrace(System.out);
 				}
-	
-				// Start JDI connection (try 10 times)
-				for (int i = 0; i < 10; i++) {
+
+				// Start JDI connection
+				int attempts = 30;
+				Instant start = Instant.now();
+				for (int i = 0; i < attempts; i++) {
 					try {
 						VirtualMachineManager manager = org.eclipse.jdi.Bootstrap.virtualMachineManager();
 						List connectors = manager.attachingConnectors();
 						if (connectors.size() == 0) {
-							System.err.println(getName() + ": could not get attachingConnectors() from VM");
+							System.out.println(getName() + ": could not get attachingConnectors() from VM");
 							break;
 						}
 						AttachingConnector connector = (AttachingConnector)connectors.get(0);
@@ -98,26 +102,30 @@
 						}
 						argument = (Connector.Argument)args.get("timeout");
 						if (argument != null) {
-							argument.setValue("20000");
+							argument.setValue("30000");
 						}
 						this.vm = connector.attach(args);
 						System.out.println(getName() + ": connected to VM using port " + debugPort);
-						
+
 						// workaround pb with some VMs
 						this.vm.resume();
-	
+
 						break;
 					} catch (IllegalConnectorArgumentsException | IOException e) {
-						e.printStackTrace();
+						e.printStackTrace(System.out);
 						try {
 							System.out.println(getName() + ": could not contact the VM at " + launcher.getTargetAddress() + ":" + debugPort + ". Retrying...");
-							Thread.sleep(100);
+							Thread.sleep(1000);
 						} catch (InterruptedException e2) {
-							e2.printStackTrace();
+							e2.printStackTrace(System.out);
 						}
 					}
 				}
 				if (this.vm == null) {
+					Duration duration = Duration.between(start, Instant.now());
+					System.out.println(getName() + ": could NOT contact the VM at " + launcher.getTargetAddress() + ":"
+							+ debugPort + ". Stop trying after " + attempts + " attempts, took " + duration.getSeconds()
+							+ " seconds");
 					if (this.launchedVM != null) {
 						// If the VM is not running, output error stream
 						try {
@@ -131,9 +139,9 @@
 								} while (read != -1);
 							}
 						} catch (TargetException | IOException e) {
-							e.printStackTrace();
+							e.printStackTrace(System.out);
 						}
-	
+
 						// Shut it down
 						try {
 							if (this.target != null) {
@@ -144,37 +152,38 @@
 								try {
 									Thread.sleep(retry * 100);
 								} catch (InterruptedException e) {
-									e.printStackTrace();
+									e.printStackTrace(System.out);
 								}
 							}
 							if (this.launchedVM.isRunning()) {
 								this.launchedVM.shutDown();
 							}
 						} catch (TargetException e) {
-							e.printStackTrace();
+							e.printStackTrace(System.out);
 						}
 					}
-					System.err.println(getName() + ": could not contact the VM");
+					System.out.println(getName() + ": could not contact the VM at port " + debugPort);
 					return;
 				}
-	
+
 				// Create context
 				this.context = new EvaluationContext();
-	
+
 				// Create target
 				this.target = new TargetInterface();
-				
+
 				// allow 30s max to connect (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=188127)
 				// Increased to 60 s for https://bugs.eclipse.org/bugs/show_bug.cgi?id=547417
-				this.target.connect(evalServer, 60000); 
-	
+				this.target.connect(evalServer, 60000);
+
 				assertTrue(getName() + ": failed to connect VM server", this.target.isConnected());
-				
+
 				System.out.println(getName() + ": connected to target using port " + debugPort);
-				
+
 				// Create name environment
 				this.env = new FileSystem(Util.getJavaClassLibs(), new String[0], null);
 			} catch (IOException e1) {
+				e1.printStackTrace(System.out);
 				throw new Error(getName() + ": Failed to open socket", e1);
 			}
 		}
diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
index c3713e4..18bc7cd 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.10.900.qualifier
+Bundle-Version: 3.10.950.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 6999cd8..ce350db 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -15,12 +15,12 @@
   <parent>
     <artifactId>tests-pom</artifactId>
     <groupId>eclipse.jdt.core</groupId>
-    <version>4.12.0-SNAPSHOT</version>
+    <version>4.13.0-SNAPSHOT</version>
     <relativePath>../tests-pom/</relativePath>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.core.tests.model</artifactId>
-  <version>3.10.900-SNAPSHOT</version>
+  <version>3.10.950-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter10Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter10Test.java
index 5cc9586..e3d1479 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter10Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter10Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2018 IBM Corporation and others.
+ * Copyright (c) 2018, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -36,7 +36,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST_INTERNAL_JLS11);
+		this.ast = AST.newAST(AST_INTERNAL_JLS11, true);
 	}
 
 	public ASTConverter10Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter11Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter11Test.java
index 7c99dcb..1da1818 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter11Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter11Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2018 IBM Corporation and others.
+ * Copyright (c) 2018, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -26,7 +26,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST_INTERNAL_JLS11);
+		this.ast = AST.newAST(AST_INTERNAL_JLS11, true);
 	}
 
 	public ASTConverter11Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter12Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter12Test.java
index 7efc9f1..9751f23 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter12Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter12Test.java
@@ -44,7 +44,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getAST12());
+		this.ast = AST.newAST(getAST12(), true);
 	}
 
 	public ASTConverter12Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
index 21383f0..0b77971 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation and others.
+ * Copyright (c) 2011, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -44,7 +44,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS4());
+		this.ast = AST.newAST(getJLS4(), false);
 	}
 
 	public ASTConverter15JLS4Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
index 546c5a5..942eaaf 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2016 IBM Corporation and others.
+ * Copyright (c) 2011, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -44,7 +44,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS8());
+		this.ast = AST.newAST(getJLS8(), false);
 	}
 
 	public ASTConverter15JLS8Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java
index 00cd53b..b33268d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.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
@@ -47,7 +47,7 @@
 	
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTConverter15Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter16Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter16Test.java
index 7df3973..fad0644 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter16Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter16Test.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
@@ -33,7 +33,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTConverter16Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java
index fbd94db..93176e7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.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
@@ -63,7 +63,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS4());
+		this.ast = AST.newAST(getJLS4(), false);
 	}
 
 	public ASTConverter17Test(String name) {
@@ -458,7 +458,7 @@
 	 * Binary literals with underscores
 	 */
 	public void test0012() throws JavaModelException {
-		AST localAst= AST.newAST(getJLS4());
+		AST localAst= AST.newAST(getJLS4(), false);
 		NumberLiteral literal= localAst.newNumberLiteral();
 		try {
 			literal.setToken("0b1010");
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
index 8129449..568caf7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
@@ -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
@@ -40,7 +40,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getAST8());
+		this.ast = AST.newAST(getAST8(), false);
 	}
 
 	public ASTConverter18Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
index 1193890..74a2b6c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
@@ -48,7 +48,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getAST9());
+		this.ast = AST.newAST(getAST9(), false);
 	}
 	/**
 	 * @deprecated
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java
index f4d1f0e..a86f1d8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.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
@@ -28,7 +28,7 @@
 	
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTConverterAST3Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
index 4b77b6e..8d2f911 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 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
@@ -28,7 +28,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS4());
+		this.ast = AST.newAST(getJLS4(), false);
 	}
 
 	public ASTConverterAST4Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
index 9e617b1..8fe1f1d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2016 IBM Corporation and others.
+ * Copyright (c) 2011, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -28,7 +28,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS8());
+		this.ast = AST.newAST(getJLS8(), false);
 	}
 
 	public ASTConverterAST8Test(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBindingsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBindingsTest.java
index ab9fedc..00ea0a5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBindingsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBindingsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 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
@@ -487,7 +487,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTConverterBindingsTest(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterRecoveryTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterRecoveryTest.java
index 713b126..39131fd 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterRecoveryTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterRecoveryTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -58,7 +58,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public void test0001() throws JavaModelException {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java
index dfafd6d..9e33ef5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.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
@@ -31,7 +31,7 @@
 	/** @deprecated using deprecated code */
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS2);
+		this.ast = AST.newAST(AST.JLS2, false);
 	}
 
 	public ASTConverterTest(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
index cfd4957..8919e0c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 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
@@ -38,7 +38,7 @@
 	/** @deprecated using deprecated code */
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS2);
+		this.ast = AST.newAST(AST.JLS2, false);
 	}
 
 	public ASTConverterTest2(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
index e7de571..b0dced2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 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
@@ -120,7 +120,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTConverterTestAST3_2(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
index bd092ec..fb679ff 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2017 IBM Corporation and others.
+ * Copyright (c) 2011, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -117,7 +117,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS4());
+		this.ast = AST.newAST(getJLS4(), false);
 	}
 
 	public ASTConverterTestAST4_2(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
index 59bca4a..cbb10de 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2018 IBM Corporation and others.
+ * Copyright (c) 2011, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -118,7 +118,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS8());
+		this.ast = AST.newAST(getJLS8(), false);
 	}
 
 	public ASTConverterTestAST8_2(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java
index 6b421b9..7c1aad5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.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
@@ -136,7 +136,7 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 
-		this.ast = AST.newAST(this.API_LEVEL);
+		this.ast = AST.newAST(this.API_LEVEL, true);
 		this.N1 = this.ast.newSimpleName("N"); //$NON-NLS-1$
 		this.N2 = this.ast.newSimpleName("M"); //$NON-NLS-1$
 		this.N3 = this.ast.newSimpleName("O"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodeFinderTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodeFinderTest.java
index 1c47267..5747a47 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodeFinderTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodeFinderTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 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
@@ -30,7 +30,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTNodeFinderTest(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTParserTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTParserTest.java
index 420cc2c..82c5d57 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTParserTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -54,7 +54,7 @@
 
 	protected void setUp() throws Exception {
 		super.setUp();
-		this.ast = AST.newAST(this.API_LEVEL);
+		this.ast = AST.newAST(this.API_LEVEL, true);
 		this.parser = ASTParser.newParser(this.API_LEVEL);
 	}
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTPositionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTPositionsTest.java
index 0181039..23085d8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTPositionsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTPositionsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 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
@@ -28,7 +28,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getJLS3());
+		this.ast = AST.newAST(getJLS3(), false);
 	}
 
 	public ASTPositionsTest(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
index 24ed63d..92aada9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
@@ -65,7 +65,7 @@
 
 	protected void setUp() throws Exception {
 		super.setUp();
-		this.ast = AST.newAST(this.API_LEVEL);
+		this.ast = AST.newAST(this.API_LEVEL, true);
 		this.parser = ASTParser.newParser(this.API_LEVEL);
 	}
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
index 34be3d5..062e772 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
@@ -787,7 +787,7 @@
 
 	protected void setUp() throws Exception {
 		super.setUp();
-		this.ast = AST.newAST(this.API_LEVEL);
+		this.ast = AST.newAST(this.API_LEVEL, true);
 	}
 
 	protected void tearDown() throws Exception {
@@ -815,7 +815,7 @@
 	 */
 	public void testExampleSnippets() {
 		{
-			AST localAst = AST.newAST(this.ast.apiLevel());
+			AST localAst = AST.newAST(this.ast.apiLevel(), true);
 			CompilationUnit cu = localAst.newCompilationUnit();
 
 			// package com.example;
@@ -1155,7 +1155,7 @@
 
 		// check that a child from a different AST is detected
 		try {
-			AST newAST = AST.newAST(node.getAST().apiLevel());
+			AST newAST = AST.newAST(node.getAST().apiLevel(), true);
 			prop.set(prop.sample(newAST, false));
 			assertTrue(false);
 		} catch (RuntimeException e) {
@@ -1262,7 +1262,7 @@
 
 		// check that a child from a different AST is detected
 		try {
-			AST newAST = AST.newAST(node.getAST().apiLevel());
+			AST newAST = AST.newAST(node.getAST().apiLevel(), true);
 			children.add(prop.sample(newAST, false));
 			assertTrue(false);
 		} catch (RuntimeException e) {
@@ -1319,9 +1319,9 @@
 		assertTrue(a0.apiLevel() == AST.JLS2);
 		AST a1 = new AST(new HashMap()); // deprecated, but still 2.0
 		assertTrue(a1.apiLevel() == AST.JLS2);
-		AST a2 = AST.newAST(AST.JLS2);
+		AST a2 = AST.newAST(AST.JLS2, false);
 		assertTrue(a2.apiLevel() == AST.JLS2);
-		AST a3 = AST.newAST(JLS3_INTERNAL);
+		AST a3 = AST.newAST(JLS3_INTERNAL, false);
 		assertTrue(a3.apiLevel() == JLS3_INTERNAL);
 
 		// modification count is always non-negative
@@ -1771,43 +1771,43 @@
 	}
 
 	public void testStringLiteralUnicode() {
-		AST localAst = AST.newAST(this.ast.apiLevel());
+		AST localAst = AST.newAST(this.ast.apiLevel(), true);
 		StringLiteral literal = localAst.newStringLiteral();
 		literal.setEscapedValue("\"hello\\u0026\\u0050worl\\u0064\""); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("hello&Pworld")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setEscapedValue("\"hello\\nworld\""); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("hello\nworld")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setLiteralValue("hello\nworld"); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("hello\nworld")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setLiteralValue("\n"); //$NON-NLS-1$
 		assertTrue(literal.getEscapedValue().equals("\"\\n\"")); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("\n")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setEscapedValue("\"hello\\\"world\""); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("hello\"world")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setLiteralValue("hello\\u0026world"); //$NON-NLS-1$
 		assertTrue(literal.getLiteralValue().equals("hello\\u0026world")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setLiteralValue("hello\\u0026world"); //$NON-NLS-1$
 		assertTrue(literal.getEscapedValue().equals("\"hello\\\\u0026world\"")); //$NON-NLS-1$
 
-		localAst = AST.newAST(this.ast.apiLevel());
+		localAst = AST.newAST(this.ast.apiLevel(), true);
 		literal = localAst.newStringLiteral();
 		literal.setLiteralValue("\\u0001"); //$NON-NLS-1$
 		assertTrue(literal.getEscapedValue().equals("\"\\\\u0001\"")); //$NON-NLS-1$
@@ -6412,7 +6412,7 @@
 		assertTrue(y.subtreeMatch(new CheckPositionsMatcher(), x));
 
 		// different AST clone
-		AST newAST = AST.newAST(this.ast.apiLevel());
+		AST newAST = AST.newAST(this.ast.apiLevel(), true);
 		ASTNode z = ASTNode.copySubtree(newAST, x);
 		assertTrue(x.subtreeMatch(new CheckPositionsMatcher(), z));
 		assertTrue(z.subtreeMatch(new CheckPositionsMatcher(), x));
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
index c5e62c6..670faf9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
@@ -160,7 +160,7 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 
-		this.ast = AST.newAST(this.API_LEVEL);
+		this.ast = AST.newAST(this.API_LEVEL, true);
 		this.N1 = this.ast.newSimpleName("N"); //$NON-NLS-1$
 		this.N1S = "[(nSNNnS)]"; //$NON-NLS-1$
 		this.N2 = this.ast.newSimpleName("M"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
index dd4ad11..1da23d2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
@@ -26,7 +26,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST_INTERNAL_JLS11);
+		this.ast = AST.newAST(AST_INTERNAL_JLS11, false);
 	}
 
 	public TypeAnnotationsConverterTest(String name) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
index 57abd10..829dcf9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
@@ -81,7 +81,7 @@
 	}
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(getAST8());
+		this.ast = AST.newAST(getAST8(), false);
 	}
 	/**
 	 * @deprecated
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java
index 936744c..6a97e9c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java
@@ -113,7 +113,8 @@
 
 private String expectedFormattedSource(String source) {
 	DefaultCodeFormatter codeFormatter = codeFormatter();
-	Scanner scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_4/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+	Scanner scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_4/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/,
+			codeFormatter.previewEnabled);
 	CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
 	CompilationUnitDeclaration compilationUnitDeclaration = codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true);
 	scanner.setSource(source.toCharArray());
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
index 5f37bc3..487061a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java
@@ -219,6 +219,8 @@
 		ResolveTests9.class,
 
 		NullAnnotationModelTests9.class,
+
+		JavaModelManagerTests.class,
 	};
 
 	Class[] deprecatedClasses = getDeprecatedJDOMTestClasses();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
index 0fc84e4..3dbfe28 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
@@ -1596,4 +1596,32 @@
 		deleteProject(project1);
 	}
 }
+public void testBug548888() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL19_LIB", "org.eclipse.jdt.core.tests.model.TEST_CONTAINER"}, "bin", "9");
+	try  {
+		project1.open(null);
+
+		String content = 
+				"/**\n" +
+				"  * @see List\n" + 
+				"  */\n" + 
+				"module firstmod {\n" + 
+				"}\n";
+		String filePath = "/Completion9_1/src/module-info.java";
+		String completeBehind="List";
+		createFile(filePath, content);
+		int cursorLocation = content.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		waitUntilIndexesReady();
+
+		ICompilationUnit unit = getCompilationUnit(filePath);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "List[TYPE_REF]{java.util.List, java.util, Ljava.util.List;, null, 53}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+	}
+}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaModelManagerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaModelManagerTests.java
new file mode 100644
index 0000000..65b052d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaModelManagerTests.java
@@ -0,0 +1,176 @@
+package org.eclipse.jdt.core.tests.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IOrdinaryClassFile;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.nd.indexer.Indexer;
+
+public class JavaModelManagerTests extends AbstractJavaModelTests {
+
+	private static final IProgressMonitor NULL_MONITOR = new NullProgressMonitor();
+	private static final String PROJECT_NAME = JavaModelManagerTests.class.getSimpleName();
+
+	public JavaModelManagerTests(String name) {
+		super(name);
+	}
+
+	/**
+	 * Test for Bug 548456 - Concurrency problem with JavaModelManager and JavaElement.openWhenClosed()
+	 *
+	 * We create a project with a jar on its class path and ask after {@link JavaElement#exists()}
+	 * for a class in the jar. We do so from 2 different threads in parallel; with sufficient repetitions
+	 * we hope to run into the race condition described in the bug.
+	 */
+	public void testBug548456_concurrentElementInfoAccess() throws Exception {
+		int iterations = 20;
+		int numberOfThreads = 10;
+		for (int i = 0; i < iterations; ++i) {
+			doTestBug548456_concurrentCallBinaryTypeExists(numberOfThreads);
+		}
+	}
+
+	private void doTestBug548456_concurrentCallBinaryTypeExists(int numberOfThreads) throws Exception {
+		final IJavaProject project = setUpJavaProject(PROJECT_NAME);
+		try {
+			buildProject(project);
+			assertHasNoBuildProblems(project);
+
+			CountDownLatch latch = new CountDownLatch(numberOfThreads);
+			List<CheckIfTypeExists> runnables = new ArrayList<>(numberOfThreads);
+			for (int i = 0; i < numberOfThreads; ++i) {
+				CheckIfTypeExists runnable = new CheckIfTypeExists(project, latch);
+				runnables.add(runnable);
+			}
+
+			List<Thread> threads = startThreads(runnables);
+
+			boolean interrupted = false;
+			for (Thread thread : threads) {
+				try {
+					thread.join();
+				} catch (InterruptedException e) {
+					// we join all threads regardless of interruption, to be sure we don't leave running threads after this method done
+					interrupted = true;
+				}
+			}
+			assertFalse("waiting on test threads to finish must not be interrupted", interrupted);
+
+			for (CheckIfTypeExists runnable : runnables) {
+				assertTrue("expected type for test source to exist, despite concurrent access to JavaModelManager", runnable.typeExists);
+			}
+		} finally {
+			deleteProject(PROJECT_NAME);
+		}
+	}
+
+	private static List<Thread> startThreads(List<CheckIfTypeExists> runnables) {
+		List<Thread> threads = new ArrayList<>(runnables.size());
+		for (CheckIfTypeExists runnable : runnables) {
+			Thread thread = new Thread(runnable);
+			threads.add(thread);
+			thread.start();
+		}
+		return threads;
+	}
+
+	class CheckIfTypeExists implements Runnable {
+
+		private final IJavaProject project;
+		private final CountDownLatch latch;
+
+		boolean typeExists = false;
+
+		CheckIfTypeExists(IJavaProject project, CountDownLatch latch) {
+			this.project = project;
+			this.latch = latch;
+		}
+
+		@Override
+		public void run() {
+			IType type = retrieveTestType(this.project);
+			// we use a CountDownLatch to ensure the thread calls to IJavaElement.exists() are running as close together as possible
+			this.latch.countDown();
+			this.typeExists = type.exists();
+		}
+	}
+
+	static IType retrieveTestType(IJavaProject project) {
+		IFile jarResource = project.getProject().getFile("lib.jar");
+		IPackageFragmentRoot root = project.getPackageFragmentRoot(jarResource);
+		IPackageFragment packageFragment = root.getPackageFragment("p");
+		IClassFile classFile = packageFragment.getClassFile("X.class");
+		IOrdinaryClassFile ordinaryClassFile = (IOrdinaryClassFile) classFile;
+		IType type = ordinaryClassFile.getType();
+		return type;
+	}
+
+	private static void buildProject(IJavaProject javaProject) throws Exception {
+		IProject project = javaProject.getProject();
+		refreshProject(project);
+		project.build(IncrementalProjectBuilder.CLEAN_BUILD, NULL_MONITOR);
+		refreshProject(project);
+		project.build(IncrementalProjectBuilder.FULL_BUILD, NULL_MONITOR);
+		Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_BUILD, null);
+		Indexer.getInstance().waitForIndex(null);
+		refreshProject(project);
+	}
+
+	private static void refreshProject(IProject project) throws CoreException {
+		project.refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR);
+		waitForManualRefresh();
+	}
+
+	private static void assertHasNoBuildProblems(IJavaProject javaProject) throws Exception {
+		IProject project = javaProject.getProject();
+		List<IMarker> modelProblems = getTestProjectErrorMarkers(project);
+		assertTrue("expected no problems when building, but got:" + System.lineSeparator() + toString(modelProblems),
+				modelProblems.isEmpty());
+	}
+
+	private static List<IMarker> getTestProjectErrorMarkers(IProject project) throws Exception {
+		IMarker[] problemMarkers = project.findMarkers(null, true, IResource.DEPTH_ZERO);
+		List<IMarker> errorMarkers = new ArrayList<>();
+		for (IMarker problemMarker : problemMarkers) {
+			int severity = problemMarker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO);
+			if (severity == IMarker.SEVERITY_ERROR) {
+				errorMarkers.add(problemMarker);
+			}
+		}
+		return errorMarkers;
+	}
+
+	private static String toString(List<IMarker> markers) throws Exception {
+		StringBuilder sb = new StringBuilder();
+		for (IMarker marker : markers) {
+			sb.append("Message: ");
+			sb.append((marker.getAttribute(IMarker.MESSAGE)));
+			sb.append(System.lineSeparator());
+			sb.append("Location: ");
+			sb.append(marker.getAttribute(IMarker.LOCATION));
+			sb.append(System.lineSeparator());
+			sb.append("Line: ");
+			sb.append(marker.getAttribute(IMarker.LINE_NUMBER));
+			sb.append(System.lineSeparator());
+		}
+		String fatalProblemsAsText = sb.toString();
+		return fatalProblemsAsText;
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 5b8459f..8972339 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -4238,8 +4238,8 @@
 			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
 			IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
 			assertMarkers("Unexpected markers",
-					"The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" + 
-					"The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files",
+					"Name of automatic module \'test\' is unstable, it is derived from the module\'s file name.\n" + 
+					"The type org.astro.World is not accessible",
 					markers);
 		} finally {
 			this.deleteProject("test");
@@ -8704,6 +8704,80 @@
 			deleteProject(prjB);
 		}
 	}
+	public void testBug547181() throws CoreException {
+		IJavaProject prjA = createJava9Project("A");
+		IJavaProject prjB = createJava9Project("B");
+		IJavaProject prjC = createJava9Project("C");
+		IJavaProject prjD = createJava9Project("D");
+		try {
+			createFile("A/src/module-info.java",
+				"module A {\n" + 
+				" exports p1.p2;\n" +
+				"}\n");
+			createFolder("A/src/p1/p2");
+			createFile("A/src/p1/p2/X.java",
+					"package p1.p2;\n" + 
+					"public class X {\n" + 
+					"}\n");
+
+			addModularProjectEntry(prjB, prjA);
+			addModularProjectEntry(prjD, prjA);
+			addModularProjectEntry(prjD, prjB);
+			addModularProjectEntry(prjD, prjC);
+
+			createFile("B/src/module-info.java",
+					"module B {\n" + 
+						" requires A;\n" +
+						" exports p1;\n" +
+					"}\n");
+			createFolder("B/src/p1");
+			createFile("B/src/p1/Y.java",
+				"package p1;\n" + 
+				"import p1.p2.X;\n" + 
+				"public class Y {\n" + 
+				"	private void f(X x) {}\n" + 
+				"}\n");
+			
+			createFile("C/src/module-info.java",
+					"module C {\n" + 
+					" exports p1.p2;\n" +
+					"}\n");
+			createFolder("C/src/p1/p2");
+			createFile("C/src/p1/p2/X.java",
+					"package p1.p2;\n" + 
+					"public class X {\n" + 
+					"}\n");
+			
+			createFile("D/src/module-info.java",
+					"module D {\n" + 
+						" requires B;\n" +
+						" requires C;\n" +
+					"}\n");
+			
+			createFolder("D/src/usage");
+			createFile("D/src/usage/AAA.java",
+					"package usage;\n" + 
+					"import p1.Y;\n" + 
+					"public class AAA {\n" + 
+					" Y y;\n" + 
+					"}\n");
+			createFile("D/src/usage/Usage.java",
+					"package usage;\n" + 
+					"import p1.p2.X;\n" + 
+					"public class Usage {\n" + 
+					" X x;\n" + 
+					"}\n");
+			
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			assertNoErrors();
+
+		} finally {
+			deleteProject(prjA);
+			deleteProject(prjB);
+			deleteProject(prjC);
+			deleteProject(prjD);
+		}
+	}
 	protected void assertNoErrors() throws CoreException {
 		for (IProject p : getWorkspace().getRoot().getProjects()) {
 			int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
index 2a2db52..4f85147 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
@@ -851,4 +851,99 @@
 		deleteProject(p2);
 	}
 }
+public void testBug547113() throws CoreException {
+	if (!isJRE9)
+		return;
+	IJavaProject unnamed = createJava9Project("unnamed");
+	IJavaProject a = createJava9Project("a");
+	IJavaProject b = createJava9Project("b");
+	IJavaProject c = createJava9Project("c");
+	try {
+		createFolder("a/src/com/example/a");
+		createFile("a/src/com/example/Base.java",
+				"package com.example;\n" + 
+				"\n" + 
+				"public class Base {}\n");
+		createFile("a/src/com/example/a/A.java",
+				"package com.example.a;\n" + 
+				"\n" + 
+				"public class A {}\n");
+		createFile("a/src/module-info.java",
+				"open module com.example.a {\n" + 
+				"	exports com.example;\n" + 
+				"	exports com.example.a;\n" + 
+				"	\n" + 
+				"	requires unnamed;\n" + 
+				"}\n");
+		addModularProjectEntry(a, unnamed);
+
+		createFolder("b/src/com/example/b");
+		createFile("b/src/com/example/b/B.java",
+				"package com.example.b;\n" + 
+				"\n" + 
+				"import com.example.Base;\n" + 
+				"import com.example.a.A;\n" + 
+				"\n" + 
+				"public class B {\n" + 
+				"\n" + 
+				"	public void a(A a) {\n" + 
+				"		System.out.println(a);\n" + 
+				"	}\n" + 
+				"\n" + 
+				"	public void base(Base base) {\n" + 
+				"		System.out.println(base);\n" + 
+				"	}\n" + 
+				"\n" + 
+				"}\n");
+		createFile("b/src/module-info.java",
+				"open module com.example.b {\n" + 
+				"	exports com.example.b;\n" + 
+				"	requires transitive com.example.a;\n" + 
+				"}\n");
+		addModularProjectEntry(b, a);
+		addModularProjectEntry(b, unnamed);
+
+		createFolder("c/src/com/example/c");
+		String cSource = "package com.example.c;\n" + 
+				"\n" + 
+				"import com.example.Base;\n" + 
+				"import com.example.a.A;\n" + 
+				"import com.example.b.B;\n" + 
+				"\n" + 
+				"public class C {\n" + 
+				"\n" + 
+				"	public static void main(String[] args) {\n" + 
+				"		new B().a(new A());\n" + 
+				"		new B().base(new Base());\n" + 
+				"		System.out.println(\"done.\");\n" + 
+				"	}\n" + 
+				"}\n";
+		createFile("c/src/com/example/c/C.java", cSource);
+		createFile("c/src/module-info.java",
+				"open module com.example.c {\n" + 
+				"	exports com.example.c;\n" + 
+				"	requires com.example.b;\n" + 
+				"}\n");
+		addModularProjectEntry(c, a);
+		addModularProjectEntry(c, b);
+		addModularProjectEntry(c, unnamed);
+
+		waitForAutoBuild();
+
+		this.workingCopy.discardWorkingCopy();
+		this.problemRequestor.initialize(cSource.toCharArray());
+		this.workingCopy = getCompilationUnit("c/src/com/example/c/C.java").getWorkingCopy(this.wcOwner, null);
+		this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray());
+		this.workingCopy.reconcile(AST_INTERNAL_JLS11, true, this.wcOwner, null);
+		assertProblems("Expecting no problems",
+				"----------\n" +
+				"----------\n",
+				this.problemRequestor);
+	} finally {
+		deleteProject(unnamed);
+		deleteProject(a);
+		deleteProject(b);
+		deleteProject(c);
+	}
+}
 }
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..acfcedc 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..e604f74 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/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
index 3788071..ecf0daa 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java
@@ -2584,7 +2584,7 @@
 
 		String[] order= new String[] { "java.util", "java.io", "java.net" };
 		int threshold= 99;
-		AST ast= AST.newAST(JLS3_INTERNAL);
+		AST ast= AST.newAST(JLS3_INTERNAL, false);
 		ImportRewrite importsRewrite= newImportsRewrite(cu2, order, threshold, threshold, true);
 		{
 			IJavaElement[] elements= cu1.codeSelect(content.indexOf("IOException"), "IOException".length());
@@ -2657,7 +2657,7 @@
 
 		String[] order= new String[] { "java.util", "java.io", "java.net" };
 		int threshold= 99;
-		AST ast= AST.newAST(JLS3_INTERNAL);
+		AST ast= AST.newAST(JLS3_INTERNAL, false);
 		ImportRewrite importsRewrite= newImportsRewrite(cu2, order, threshold, threshold, true);
 		{
 			IJavaElement[] elements= cu1.codeSelect(content.indexOf("Map"), "Map".length());
diff --git a/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.classpath b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.classpath
new file mode 100644
index 0000000..068e118
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+    <classpathentry kind="src" path=""/>
+    <classpathentry kind="var" path="JCL_LIB" sourcepath="JCL_SRC" rootpath="JCL_SRCROOT"/>
+    <classpathentry kind="lib" path="lib.jar"/>
+    <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.project b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.project
new file mode 100644
index 0000000..d277b75
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>JavaModelManagerTests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/lib.jar b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/lib.jar
new file mode 100644
index 0000000..e2aadfd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/JavaModelManagerTests/lib.jar
Binary files differ
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.pde.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.pde.prefs
index 35bb407..9251e60 100644
--- a/org.eclipse.jdt.core/.settings/org.eclipse.pde.prefs
+++ b/org.eclipse.jdt.core/.settings/org.eclipse.pde.prefs
@@ -26,7 +26,7 @@
 compilers.p.unknown-element=1
 compilers.p.unknown-identifier=1
 compilers.p.unknown-resource=1
-compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-ex-points=1
 compilers.p.unresolved-import=0
 compilers.s.create-docs=false
 compilers.s.doc-folder=doc
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 1896387..6d5d6b7 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true
-Bundle-Version: 3.18.0.OTDT_r274_qualifier
+Bundle-Version: 3.19.0.OTDT_r274_qualifier
 Bundle-Activator: org.eclipse.jdt.core.JavaCore
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
index 06d3535..2bf9db3 100644
--- a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
@@ -163,9 +163,7 @@
 		if (getSourcepathMethod != null) {
 			try {
 				compileSourcePath = (Path) getSourcepathMethod.invoke(this.attributes, (Object[]) null);
-			} catch (IllegalAccessException e) {
-				// should never happen
-			} catch (InvocationTargetException e) {
+			} catch (IllegalAccessException | InvocationTargetException e) {
 				// should never happen
 			}
 		}
@@ -211,9 +209,7 @@
 			if (getDebugLevelMethod != null) {
 				try {
 					debugLevel = (String) getDebugLevelMethod.invoke(this.attributes, (Object[]) null);
-				} catch (IllegalAccessException e) {
-					// should never happen
-				} catch (InvocationTargetException e) {
+				} catch (IllegalAccessException | InvocationTargetException e) {
 					// should never happen
 				}
 			}
@@ -365,9 +361,7 @@
 		if (getCurrentCompilerArgsMethod != null) {
 			try {
 				compilerArgs = (String[]) getCurrentCompilerArgsMethod.invoke(this.attributes, (Object[]) null);
-			} catch (IllegalAccessException e) {
-				// should never happen
-			} catch (InvocationTargetException e) {
+			} catch (IllegalAccessException | InvocationTargetException e) {
 				// should never happen
 			}
 		}
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 d375936..ae30ebd 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
@@ -40,6 +40,13 @@
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -166,9 +173,7 @@
 						fetchAccessRestriction(qualifiedBinaryFileName),
 						modName);
 			}
-		} catch (IOException e) {
-			// treat as if file is missing
-		} catch (ClassFormatException e) {
+		} catch (IOException | ClassFormatException e) {
 			// treat as if file is missing
 		}
 	}
@@ -343,6 +348,27 @@
 		return hasDeclaration;
 	});
 }
+
+@Override
+public char[][] listPackages() {
+	Set<String> packageNames = new HashSet<>();
+	try {
+		Path basePath = FileSystems.getDefault().getPath(this.path);
+		Files.walkFileTree(basePath, new SimpleFileVisitor<Path>() {
+			@Override
+			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+				if (file.toString().toLowerCase().endsWith(SUFFIX_STRING_class)) {
+					packageNames.add(file.getParent().relativize(basePath).toString().replace('/', '.'));
+				}
+				return FileVisitResult.CONTINUE;
+			}
+		});
+	} catch (IOException e) {
+		// treat as if files are missing
+	}
+	return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
 @Override
 public void reset() {
 	super.reset();
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 cb607ad..c565187 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
@@ -150,9 +150,7 @@
 			}
 			return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName);
 		}
-	} catch(ClassFormatException e) {
-		// treat as if class file is missing
-	} catch (IOException e) {
+	} catch (ClassFormatException | IOException e) {
 		// treat as if class file is missing
 	}
 	return null;
@@ -260,6 +258,19 @@
 	}	
 	return false;
 }
+
+@Override
+public char[][] listPackages() {
+	Set<String> packageNames = new HashSet<>();
+	for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+		String fileName = e.nextElement().getName();
+		int lastSlash = fileName.lastIndexOf('/');
+		if (lastSlash != -1 && fileName.toLowerCase().endsWith(SUFFIX_STRING_class))
+			packageNames.add(fileName.substring(0, lastSlash).replace('/', '.'));
+	}
+	return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
 @Override
 public void reset() {
 	super.reset();
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
index 0be7129..a848b11 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
@@ -95,9 +95,7 @@
 				char[] modName = moduleName != null ? moduleName.toCharArray() : null;
 				return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName);
 			}
-		} catch(ClassFormatException e) {
-			// Continue
-		} catch (IOException e) {
+		} catch (ClassFormatException | IOException e) {
 			// continue
 		}
 		return null;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java
index 48a119a..0709ad5 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java
@@ -95,9 +95,7 @@
 				char[] modName = moduleName != null ? moduleName.toCharArray() : null;
 				return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName);
 			}
-		} catch(ClassFormatException e) {
-			// Continue
-		} catch (IOException e) {
+		} catch (ClassFormatException | IOException e) {
 			// continue
 		}
 		return null;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJmod.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJmod.java
index 47e2843..09786d6 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJmod.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJmod.java
@@ -89,9 +89,7 @@
 			}
 			return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName);
 		}
-	} catch(ClassFormatException e) {
-		// treat as if class file is missing
-	} catch (IOException e) {
+	} catch (ClassFormatException | IOException e) {
 		// treat as if class file is missing
 	}
 	return null;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
index c34ac10..03cdb86 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
@@ -113,9 +113,7 @@
 					answerModuleName = moduleName.toCharArray();
 				return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), answerModuleName);
 			}
-		} catch(ClassFormatException e) {
-			// treat as if class file is missing
-		} catch (IOException e) {
+		} catch (ClassFormatException | IOException e) {
 			// treat as if class file is missing
 		}
 		return null;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index 403ecdf..b5142d4 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.nio.file.InvalidPathException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -168,6 +169,9 @@
 
 	/** Tasks resulting from --add-reads or --add-exports command line options. */
 	Map<String,UpdatesByKind> moduleUpdates = new HashMap<>();
+
+	private boolean hasLimitModules = false;
+
 	static final boolean isJRE12Plus;
 	static {
 		isJRE12Plus = CompilerOptions.VERSION_12.equals(System.getProperty("java.specification.version")); //$NON-NLS-1$
@@ -184,6 +188,7 @@
 	final int classpathSize = classpathNames.length;
 	this.classpaths = new Classpath[classpathSize];
 	int counter = 0;
+	this.hasLimitModules = limitModules != null && !limitModules.isEmpty();
 	for (int i = 0; i < classpathSize; i++) {
 		Classpath classpath = getClasspath(classpathNames[i], encoding, null, null, null);
 		try {
@@ -204,6 +209,7 @@
 	final int length = paths.length;
 	int counter = 0;
 	this.classpaths = new FileSystem.Classpath[length];
+	this.hasLimitModules = limitedModules != null && !limitedModules.isEmpty();
 	for (int i = 0; i < length; i++) {
 		final Classpath classpath = paths[i];
 		try {
@@ -565,8 +571,8 @@
 }
 
 @Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) {
-	String qualifiedPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+	String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
 	String moduleNameString = String.valueOf(moduleName);
 
 	LookupStrategy strategy = LookupStrategy.get(moduleName);
@@ -583,6 +589,7 @@
 	}
 	// search the entire environment and answer which modules declare that package:
 	char[][] allNames = null;
+	boolean hasUnobserable = false;
 	for (Classpath cp : this.classpaths) {
 		if (strategy.matches(cp, Classpath::hasModule)) {
 			if (strategy == LookupStrategy.Unnamed) {
@@ -592,6 +599,10 @@
 			} else {
 				char[][] declaringModules = cp.getModulesDeclaringPackage(qualifiedPackageName, null);
 				if (declaringModules != null) {
+					if (cp instanceof ClasspathJrt && this.hasLimitModules) {
+						declaringModules = filterModules(declaringModules);
+						hasUnobserable |= declaringModules == null;
+					}
 					if (allNames == null)
 						allNames = declaringModules;
 					else
@@ -600,8 +611,16 @@
 			}
 		}
 	}
+	if (allNames == null && hasUnobserable)
+		return new char[][] { ModuleBinding.UNOBSERVABLE };
 	return allNames;
 }
+private char[][] filterModules(char[][] declaringModules) {
+	char[][] filtered = Arrays.stream(declaringModules).filter(m -> this.moduleLocations.containsKey(new String(m))).toArray(char[][]::new);
+	if (filtered.length == 0)
+		return null;
+	return filtered;
+}
 private Parser getParser() {
 	Map<String,String> opts = new HashMap<String, String>();
 	opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
@@ -683,6 +702,19 @@
 	return set.toArray(new char[set.size()][]);
 }
 
+@Override
+public char[][] listPackages(char[] moduleName) {
+	switch (LookupStrategy.get(moduleName)) {
+		case Named:
+			Classpath classpath = this.moduleLocations.get(new String(moduleName));
+			if (classpath != null)
+				return classpath.listPackages();
+			return CharOperation.NO_CHAR_CHAR;
+		default:
+			throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+	}
+}
+
 void addModuleUpdate(String moduleName, Consumer<IUpdatableModule> update, UpdateKind kind) {
 	UpdatesByKind updates = this.moduleUpdates.get(moduleName);
 	if (updates == null) {
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 0c0a0b3..38d1a8e 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -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
@@ -51,6 +51,8 @@
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.text.DateFormat;
@@ -228,11 +230,7 @@
 						Logger.FIELD_TABLE.put(key2, field.getName());
 					}
 				}
-			} catch (SecurityException e) {
-				e.printStackTrace();
-			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
-			} catch (IllegalAccessException e) {
+			} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
 				e.printStackTrace();
 			}
 		}
@@ -1022,6 +1020,10 @@
 					}
 				}
 			}
+			if (this.main.failOnWarning && globalWarningsCount > 0) {
+				printErr("\n"); //$NON-NLS-1$
+				printErr(this.main.bind("compile.failOnWarning")); //$NON-NLS-1$
+			}
 			if ((this.tagBits & Logger.XML) == 0) {
 				this.printlnErr();
 			}
@@ -1421,6 +1423,7 @@
 	protected FileSystem.Classpath[] checkedClasspaths;
 	// For single module mode
 	protected IModule module;
+	private String moduleVersion;
 	// paths to external annotations:
 	protected List<String> annotationPaths;
 	protected boolean annotationsFromClasspath;
@@ -1475,6 +1478,7 @@
 	protected PrintWriter out;
 	public boolean proceed = true;
 	public boolean proceedOnError = false;
+	public boolean failOnWarning = false;
 	public boolean produceRefInfo = false;
 	public int currentRepetition, maxRepetition;
 	public boolean showProgress = false;
@@ -1494,6 +1498,7 @@
 	private PrintWriter err;
 
 	protected ArrayList<CategorizedProblem> extraProblems;
+
 	public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
 	// two uses: recognize 'none' in options; code the singleton none
 	// for the '-d none' option (wherever it may be found)
@@ -1829,16 +1834,11 @@
 		if (this.systemExitWhenFinished) {
 			this.logger.flush();
 			this.logger.close();
+			if (this.failOnWarning && this.globalWarningsCount > 0) {
+				System.exit(-1);
+			}
 			System.exit(this.globalErrorsCount > 0 ? -1 : 0);
 		}
-	} catch (IllegalArgumentException e) {
-		this.logger.logException(e);
-		if (this.systemExitWhenFinished) {
-			this.logger.flush();
-			this.logger.close();
-			System.exit(-1);
-		}
-		return false;
 	} catch (Exception e) { // internal compiler failure
 		this.logger.logException(e);
 		if (this.systemExitWhenFinished) {
@@ -1853,8 +1853,13 @@
 		if (this.progress != null)
 			this.progress.done();
 	}
-	if (this.globalErrorsCount == 0 && (this.progress == null || !this.progress.isCanceled()))
-		return true;
+	if (this.progress == null || !this.progress.isCanceled()) {
+		if (this.failOnWarning && (this.globalWarningsCount > 0))
+			return false;
+		if (this.globalErrorsCount == 0)
+			return true;
+	}
+
 	return false;
 }
 
@@ -1896,6 +1901,7 @@
 	final int INSIDE_ADD_MODULES = 29;
 	final int INSIDE_RELEASE = 30;
 	final int INSIDE_LIMIT_MODULES = 31;
+	final int INSIDE_MODULE_VERSION = 32;
 
 	final int DEFAULT = 0;
 	ArrayList<String> bootclasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
@@ -2312,6 +2318,10 @@
 					mode = INSIDE_LIMIT_MODULES;
 					continue;
 				}
+				if (currentArg.equals("--module-version")) { //$NON-NLS-1$
+					mode = INSIDE_MODULE_VERSION;
+					continue;
+				}
 				if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
 					if (sourcepathClasspathArg != null) {
 						StringBuffer errorMessage = new StringBuffer();
@@ -2378,6 +2388,11 @@
 					this.proceedOnError = true;
 					continue;
 				}
+				if (currentArg.equals("-failOnWarning")) { //$NON-NLS-1$
+					mode = DEFAULT;
+					this.failOnWarning = true;
+					continue;
+				}
 				if (currentArg.equals("-time")) { //$NON-NLS-1$
 					mode = DEFAULT;
 					this.timing = TIMING_ENABLED;
@@ -3002,6 +3017,10 @@
 					this.limitedModules.add(tokenizer.nextToken().trim());
 				}
 				continue;
+			case INSIDE_MODULE_VERSION:
+				mode = DEFAULT;
+				this.moduleVersion = validateModuleVersion(currentArg);
+				continue;
 			case INSIDE_CLASSPATH_start:
 				mode = DEFAULT;
 				index += processPaths(newCommandLineArgs, index, currentArg, classpaths);
@@ -3296,6 +3315,22 @@
 		this.pendingErrors = null;
 	}
 }
+private String validateModuleVersion(String versionString) {
+	try {
+		Class<?> versionClass = Class.forName("java.lang.module.ModuleDescriptor$Version"); //$NON-NLS-1$
+		Method method = versionClass.getMethod("parse", String.class); //$NON-NLS-1$
+		try {
+			method.invoke(null, versionString);
+		} catch (InvocationTargetException e) {
+			if (e.getCause() instanceof IllegalArgumentException)
+				throw (IllegalArgumentException) e.getCause();
+		}
+	} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException e) {
+		this.logger.logWarning(this.bind("configure.no.ModuleDescriptorVersionparse")); //$NON-NLS-1$
+	}
+	return versionString;
+}
+
 private Parser getNewParser() {
 	return new Parser(new ProblemReporter(getHandlingPolicy(), 
 			new CompilerOptions(this.options), getProblemFactory()), false);
@@ -4953,6 +4988,7 @@
 			}
 		}
 	}
+	environment.moduleVersion = this.moduleVersion;
 }
 private ReferenceBinding[] processClassNames(LookupEnvironment environment) {
 	// check for .class file presence in case of apt processing
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 c66af39..6c4a820 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 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
@@ -59,6 +59,7 @@
 compile.severalInfos = {0} info
 compile.oneClassFileGenerated = [1 .class file generated]
 compile.severalClassFilesGenerated = [{0} .class files generated]
+compile.failOnWarning = error: warnings found and -failOnWarning specified
 
 ### configure
 configure.requiresJDK1.2orAbove = Need to use a JVM >= 1.2
@@ -107,6 +108,7 @@
 configure.invalidInfoOption = invalid info option: ''{0}''. Must specify an info token
 
 configure.notOnModuleSourcePath = ''{0}'' does not belong to a module on the module source path
+configure.no.ModuleDescriptorVersionparse = Could not invoke method java.lang.module.ModuleDescriptor.Version.parse(), cannot validate module version.
 
 ## configure.directoryNotExist = directory does not exist: {0}
 configure.unrecognizedOption = Unrecognized option : {0}
@@ -326,6 +328,7 @@
 \                       do not stop at first error, dumping class files with\n\
 \                       problem methods\n\
 \                       With ":Fatal", all optional errors are treated as fatal\n\
+\    -failOnWarning     fail compilation if there are warnings\n\
 \    -verbose           enable verbose output\n\
 \    -referenceInfo     compute reference info\n\
 \    -progress          show progress (only in -log mode)\n\
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 be9535e..50efb4c 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
@@ -2398,22 +2398,7 @@
 						// currently have no way to know if extends/implements are possible keywords
 					}
 			*/
-		} catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (InvalidCursorLocation e) { // may eventually report a usefull error
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (CompletionNodeFound e){ // internal failure - bugs 5618
+		} catch (IndexOutOfBoundsException | InvalidCursorLocation | AbortCompilation | CompletionNodeFound e){ // internal failure - bugs 5618
 			if(DEBUG) {
 				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
 				e.printStackTrace(System.out);
@@ -2444,6 +2429,7 @@
 				throw new CompletionNodeFound(this.parser.assistNode, null, parsedUnit.scope);
 			}
 			catch (CompletionNodeFound e) {
+				this.unitScope = parsedUnit.scope;
 				if (e.astNode != null) {
 					// if null then we found a problem in the completion node
 					if(DEBUG) {
@@ -2673,22 +2659,7 @@
 					}
 				}
 			}
-		}  catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D (added with fix of 99629)
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (InvalidCursorLocation e) { // may eventually report a usefull error (added to fix 99629)
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object (added with fix of 99629)
-			if(DEBUG) {
-				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629)
+		}  catch (IndexOutOfBoundsException | InvalidCursorLocation | AbortCompilation | CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629)
 			if(DEBUG) {
 				System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
 				e.printStackTrace(System.out);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index 42d0a40..9e7ea8a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -593,7 +593,8 @@
 				this.compilerOptions.complianceLevel,
 				null/*taskTag*/,
 				null/*taskPriorities*/,
-				true /*taskCaseSensitive*/);
+				true /*taskCaseSensitive*/,
+				this.compilerOptions.enablePreviewFeatures);
 //{ObjectTeams: configure scanner mode:
 		scanner.setOTFlags(this.compilerOptions);
 // SH}
@@ -1209,12 +1210,7 @@
 			if(this.noProposal && this.problem != null) {
 				this.requestor.acceptError(this.problem);
 			}
-		} catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
-			if(DEBUG) {
-				System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
-				e.printStackTrace(System.out);
-			}
-		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+		} catch (IndexOutOfBoundsException | AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
 			if(DEBUG) {
 				System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
 				e.printStackTrace(System.out);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index f0c3da2..33adc4d 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -5656,7 +5656,7 @@
 }
 @Override
 public void initializeScanner(){
-	this.scanner = new CompletionScanner(this.options.sourceLevel);
+	this.scanner = new CompletionScanner(this.options.sourceLevel, this.options.enablePreviewFeatures);
 //{ObjectTeams: allow to configure OT/J features:
 	this.scanner.setOTFlags(this.options);
 // SH}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
index 5406565..ceb9435 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
@@ -48,6 +48,11 @@
 	public static final char[] EmptyCompletionIdentifier = {};
 
 public CompletionScanner(long sourceLevel) {
+	this(
+		sourceLevel,
+		false /* previewEnabled */);
+}
+public CompletionScanner(long sourceLevel, boolean previewEnabled) {
 	super(
 		false /*comment*/,
 		false /*whitespace*/,
@@ -55,7 +60,8 @@
 		sourceLevel,
 		null /*taskTags*/,
 		null/*taskPriorities*/,
-		true/*taskCaseSensitive*/);
+		true/*taskCaseSensitive*/,
+		previewEnabled);
 }
 @Override
 protected boolean isAtAssistIdentifier() {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index b663873..6a6502b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -1614,7 +1614,7 @@
 // SH}
 @Override
 public void initializeScanner(){
-	this.scanner = new SelectionScanner(this.options.sourceLevel);
+	this.scanner = new SelectionScanner(this.options.sourceLevel, this.options.enablePreviewFeatures);
 //{ObjectTeams: allow to configure OT/J features:
 	this.scanner.setOTFlags(this.options);
 // SH}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
index d527414..11900eb 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
@@ -33,8 +33,8 @@
  *
  */
 
-public SelectionScanner(long sourceLevel) {
-	super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+public SelectionScanner(long sourceLevel, boolean previewEnabled) {
+	super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/, previewEnabled);
 }
 
 @Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 2829bee..80ecca0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -2580,9 +2580,7 @@
 							}
 							memberValuePairsCount++;
 							resetPosition = this.contentsOffset;
-						} catch(ClassCastException e) {
-							this.contentsOffset = resetPosition;
-						} catch(ShouldNotImplement e) {
+						} catch(ClassCastException | ShouldNotImplement e) {
 							this.contentsOffset = resetPosition;
 						}
 					}
@@ -2615,9 +2613,7 @@
 						// completely remove the annotation as its value is invalid
 						this.contentsOffset = startingContentsOffset;
 					}
-				} catch(ClassCastException e) {
-					this.contentsOffset = startingContentsOffset;
-				} catch(ShouldNotImplement e) {
+				} catch(ClassCastException | ShouldNotImplement e) {
 					this.contentsOffset = startingContentsOffset;
 				}
 			}
@@ -2849,9 +2845,10 @@
 		int flags = module.modifiers & ~(ClassFileConstants.AccModule);
 		this.contents[localContentsOffset++] = (byte) (flags >> 8);
 		this.contents[localContentsOffset++] = (byte) flags;
-		int module_version = 0;
-		this.contents[localContentsOffset++] = (byte) (module_version >> 8);
-		this.contents[localContentsOffset++] = (byte) module_version;
+		String moduleVersion = module.getModuleVersion();
+		int module_version_idx = moduleVersion == null ? 0 : this.constantPool.literalIndex(moduleVersion.toCharArray());
+		this.contents[localContentsOffset++] = (byte) (module_version_idx >> 8);
+		this.contents[localContentsOffset++] = (byte) module_version_idx;
 		int attrLength = 6;
 		
 		// ================= requires section =================
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 808b5f6..b3dd455 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -673,10 +673,7 @@
 				while (true) {
 					try {
 						unit = processingTask.removeNextUnit(); // waits if no units are in the processed queue
-					} catch (Error e) {
-						unit = processingTask.unitToProcess;
-						throw e;
-					} catch (RuntimeException e) {
+					} catch (Error | RuntimeException e) {
 						unit = processingTask.unitToProcess;
 						throw e;
 					}
@@ -708,10 +705,7 @@
 			}
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
-		} catch (Error e) {
-			this.handleInternalException(e, unit, null);
-			throw e; // rethrow
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
@@ -1174,10 +1168,7 @@
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
 			return unit == null ? this.unitsToProcess[0] : unit;
-		} catch (Error e) {
-			this.handleInternalException(e, unit, null);
-			throw e; // rethrow
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ProcessTaskManager.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ProcessTaskManager.java
index a404b72..4145514 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ProcessTaskManager.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ProcessTaskManager.java
@@ -166,13 +166,7 @@
 			}
 
 			addNextUnit(this.unitToProcess);
-		} catch (Error e) {
-			synchronized (this) {
-				this.processingThread = null;
-				this.caughtException = e;
-			}
-			return;
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			synchronized (this) {
 				this.processingThread = null;
 				this.caughtException = e;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ReadManager.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ReadManager.java
index 1d6925d..f00b44e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ReadManager.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ReadManager.java
@@ -49,12 +49,7 @@
 			else if (threadCount > CACHE_SIZE)
 				threadCount = CACHE_SIZE;
 		}
-	} catch (IllegalAccessException ignored) { // ignored
-	} catch (ClassNotFoundException e) { // ignored
-	} catch (SecurityException e) { // ignored
-	} catch (NoSuchMethodException e) { // ignored
-	} catch (IllegalArgumentException e) { // ignored
-	} catch (InvocationTargetException e) { // ignored
+	} catch (IllegalAccessException | ClassNotFoundException | SecurityException | NoSuchMethodException | IllegalArgumentException | InvocationTargetException e) { // ignored
 	}
 
 	if (threadCount > 0) {
@@ -184,13 +179,7 @@
 				}
 			}
 		}
-	} catch (Error e) {
-		synchronized (this) {
-			this.caughtException = e;
-			shutdown();
-		}
-		return;
-	} catch (RuntimeException e) {
+	} catch (Error | RuntimeException e) {
 		synchronized (this) {
 			this.caughtException = e;
 			shutdown();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
index 6cb430b..c179ed9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
@@ -37,10 +37,9 @@
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.SourceModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
@@ -195,7 +194,7 @@
 
 		this.hasResolvedPackageDirectives = true;
 
-		Set<PackageBinding> exportedPkgs = new HashSet<>();
+		Set<PlainPackageBinding> exportedPkgs = new HashSet<>();
 		for (int i = 0; i < this.exportsCount; i++) {
 			ExportsStatement ref = this.exports[i];
  			if (ref != null && ref.resolve(cuScope)) {
@@ -283,16 +282,21 @@
 	
 	private void analyseReferencedPackages(CompilationUnitScope skope) {
 		if (this.exports != null) {
-			for (ExportsStatement export : this.exports) {
-				PackageBinding pb = export.resolvedPackage;
-				if (pb == null)
-					continue;
-				if (pb instanceof SplitPackageBinding)
-					pb = ((SplitPackageBinding) pb).getIncarnation(this.binding);
-				if (pb.hasCompilationUnit(true))
-					continue;
-				skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, export);
-			}
+			analyseSomeReferencedPackages(this.exports, skope);
+		}
+		if (this.opens != null) {
+			analyseSomeReferencedPackages(this.opens, skope);
+		}
+	}
+
+	private void analyseSomeReferencedPackages(PackageVisibilityStatement[] stats, CompilationUnitScope skope) {
+		for (PackageVisibilityStatement stat : stats) {
+			PlainPackageBinding pb = stat.resolvedPackage;
+			if (pb == null)
+				continue;
+			if (pb.hasCompilationUnit(true))
+				continue;
+			skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, stat);
 		}
 	}
 
@@ -301,8 +305,7 @@
 			// collect transitively:
 			Map<String, Set<ModuleBinding>> pack2mods = new HashMap<>();
 			for (ModuleBinding requiredModule : this.binding.getAllRequiredModules()) {
-				for (PackageBinding exportedPackage : requiredModule.getExports()) {
-					exportedPackage = exportedPackage.getVisibleFor(requiredModule, true);
+				for (PlainPackageBinding exportedPackage : requiredModule.getExports()) {
 					if (this.binding.canAccess(exportedPackage)) {
 						String packName = String.valueOf(exportedPackage.readableName());
 						Set<ModuleBinding> mods = pack2mods.get(packName);
@@ -331,7 +334,7 @@
 	private void analyseOneDependency(RequiresStatement requiresStat, ModuleBinding requiredModule, CompilationUnitScope skope,
 			Map<String, Set<ModuleBinding>> pack2mods)
 	{
-		for (PackageBinding pack : requiredModule.getExports()) {
+		for (PlainPackageBinding pack : requiredModule.getExports()) {
 			Set<ModuleBinding> mods = pack2mods.get(String.valueOf(pack.readableName()));
 			if (mods != null && mods.size() > 1) {
 				CompilerOptions compilerOptions = skope.compilerOptions();
@@ -451,4 +454,12 @@
 	public void resetErrorFlag() {
 		this.ignoreFurtherInvestigation = false;
 	}
+
+	public String getModuleVersion() {
+		if (this.scope != null) {
+			LookupEnvironment env = this.scope.environment().root;
+			return env.moduleVersion;
+		}
+		return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
index 0565524..e1da2b7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
@@ -13,6 +13,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class OpensStatement extends PackageVisibilityStatement {
@@ -24,8 +25,13 @@
 		super(pkgRef, targets);
 	}
 	@Override
-	protected int computeSeverity(int problemId) {
-		return ProblemSeverities.Warning;
+	public int computeSeverity(int problemId) {
+		switch (problemId) {
+			case IProblem.PackageDoesNotExistOrIsEmpty:
+				return ProblemSeverities.Warning;
+			default:
+				return ProblemSeverities.Error;
+		}
 	}
 	@Override
 	public StringBuffer print(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
index f5e7470..b4bdbf8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
@@ -17,7 +17,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
@@ -26,7 +26,7 @@
 	public ImportReference pkgRef;
 	public ModuleReference[] targets;
 	public char[] pkgName;
-	public PackageBinding resolvedPackage;
+	public PlainPackageBinding resolvedPackage;
 
 	public PackageVisibilityStatement(ImportReference pkgRef, ModuleReference[] targets) {
 		this.pkgRef = pkgRef;
@@ -58,27 +58,15 @@
 		}
 		return !errorsExist;
 	}
-	protected int computeSeverity(int problemId) {
+	public int computeSeverity(int problemId) {
 		return ProblemSeverities.Error;
 	}
-	protected PackageBinding resolvePackageReference(Scope scope) {
+	protected PlainPackageBinding resolvePackageReference(Scope scope) {
 		if (this.resolvedPackage != null)
 			return this.resolvedPackage;
 		ModuleDeclaration exportingModule = scope.compilationUnitScope().referenceContext.moduleDeclaration;
 		ModuleBinding src = exportingModule.binding;
-		this.resolvedPackage = src != null ? src.getVisiblePackage(this.pkgRef.tokens) : null;
-		int problemId = IProblem.PackageDoesNotExistOrIsEmpty;
-		if (this.resolvedPackage == null) {
-			// TODO: need a check for empty package as well
-			scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId));
-		} else {
-			if (!this.resolvedPackage.isDeclaredIn(src)) {
-				this.resolvedPackage = null;
-				// TODO(SHMOD): specific error?
-				scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId));
-			}
-		}
-		
+		this.resolvedPackage = src != null ? src.getOrCreateDeclaredPackage(this.pkgRef.tokens) : null;
 		return this.resolvedPackage;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index 5ee01cc..e062d28 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -1186,7 +1186,12 @@
 		return this.resolvedType; // modified during checking
 	}
 // SH}
-	if (this.binding instanceof ProblemFieldBinding) {
+	Binding inaccessible = scope.environment().getInaccessibleBinding(this.tokens, scope.module());
+	if (inaccessible instanceof TypeBinding) {
+		this.indexOfFirstFieldBinding = -1;
+		this.binding = inaccessible;
+		scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
+	} else if (this.binding instanceof ProblemFieldBinding) {
 		scope.problemReporter().invalidField(this, (FieldBinding) this.binding);
 	} else if (this.binding instanceof ProblemReferenceBinding || this.binding instanceof MissingTypeBinding) {
 		scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
index b7b81f4..539caab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
@@ -15,6 +15,7 @@
 
 import java.util.function.Predicate;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
 import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
 
@@ -101,15 +102,15 @@
 	}
 	@Override
 	default boolean isPackage(char[][] parentPackageName, char[] packageName) {
-		return getModulesDeclaringPackage(parentPackageName, packageName, ModuleBinding.ANY) != null;
+		return getModulesDeclaringPackage(CharOperation.arrayConcat(parentPackageName, packageName), ModuleBinding.ANY) != null;
 	}
 
 	NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName);
 	/** Answer a type identified by the given names. moduleName may be one of the special names from ModuleBinding (ANY, ANY_NAMED, UNNAMED). */
 	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName);
-	char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName);
-	default char[][] getUniqueModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
-		char[][] allNames = getModulesDeclaringPackage(parentPackageName, name, moduleName);
+	char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName);
+	default char[][] getUniqueModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+		char[][] allNames = getModulesDeclaringPackage(packageName, moduleName);
 		if (allNames != null && allNames.length > 1) {
 			SimpleSetOfCharArray set = new SimpleSetOfCharArray(allNames.length);
 			for (char[] oneName : allNames)
@@ -139,4 +140,12 @@
 	 * @param kind selects what kind of updates should be performed
 	 */
 	default void applyModuleUpdates(IUpdatableModule module, IUpdatableModule.UpdateKind kind) { /* default: do nothing */ }
+
+	/**
+	 * Lists all packages in the module identified by the given, real module name 
+	 * (i.e., this method is implemented only for {@link LookupStrategy#Named}).
+	 * @param moduleName
+	 * @return array of flat, dot-separated package names
+	 */
+	char[][] listPackages(char[] moduleName);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
index 562c1ae..86f24f7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
@@ -75,6 +75,14 @@
 	boolean hasCompilationUnit(String qualifiedPackageName, String moduleName);
 
 	/**
+	 * Lists all packages in this modulepath entry.
+	 * @return array of flat, dot-separated package names
+	 */
+	default char[][] listPackages() {
+		return CharOperation.NO_CHAR_CHAR;
+	}
+
+	/**
 	 * Specifies whether this entry represents an automatic module.
 	 * 
 	 * @return true if this is an automatic module, false otherwise
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
index 4082b28..0704eef 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
@@ -43,7 +43,6 @@
 		}
 		@Override
 		public void accept(IUpdatableModule t) {
-			// TODO Auto-generated method stub
 			t.addExports(this.name, this.targets);
 		}
 		
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
index 50c758a..3872a02 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
@@ -26,7 +26,6 @@
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
 public interface ITypeRequestor {
 
@@ -60,13 +59,9 @@
 	 */
 	default void accept(IModule module, LookupEnvironment environment) {
 		if (module instanceof ISourceModule) {
-			try {
-				ICompilationUnit compilationUnit = ((ISourceModule) module).getCompilationUnit();
-				if (compilationUnit != null) {
-					accept(compilationUnit, null);
-				}
-			} catch (AbortCompilation abort) {
-				// silent
+			ICompilationUnit compilationUnit = ((ISourceModule) module).getCompilationUnit();
+			if (compilationUnit != null) {
+				accept(compilationUnit, null);
 			}
 		} else {
 			// handles IBinaryModule and IModule.AutoModule:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
index 080b8f8..5102e9c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
@@ -32,6 +32,7 @@
 	private static class AutomaticModuleBinding extends ModuleBinding {
 
 		boolean autoNameFromManifest;
+		boolean hasScannedPackages;
 
 		public AutomaticModuleBinding(IModule module, LookupEnvironment existingEnvironment) {
 			super(module.name(), existingEnvironment);
@@ -40,7 +41,8 @@
 			this.autoNameFromManifest = module.isAutoNameFromManifest();
 			this.requires = Binding.NO_MODULES;
 			this.requiresTransitive = Binding.NO_MODULES;
-			this.exportedPackages = Binding.NO_PACKAGES;
+			this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+			this.hasScannedPackages = false;
 		}
 		@Override
 		public boolean hasUnstableAutoName() {
@@ -58,6 +60,17 @@
 			return this.requiresTransitive;
 		}
 		@Override
+		PlainPackageBinding getDeclaredPackage(char[] flatName) {
+			if (!this.hasScannedPackages) {
+				for (char[] packageName : (((IModuleAwareNameEnvironment)this.environment.nameEnvironment).listPackages(nameForCUCheck()))) {
+					getOrCreateDeclaredPackage(CharOperation.splitOn('.', packageName));
+				}
+				this.hasScannedPackages = true;
+			}
+			return this.declaredPackages.get(flatName);
+		}
+
+		@Override
 		public char[] nameForLookup() {
 			return ANY_NAMED;
 		}
@@ -155,73 +168,51 @@
 	}
 
 	@Override
-	public PackageBinding[] getExports() {
+	public PlainPackageBinding[] getExports() {
 		if (this.exportedPackages == null && this.unresolvedExports != null)
 			resolvePackages();
 		return super.getExports();
 	}
 	
 	@Override
-	public PackageBinding[] getOpens() {
+	public PlainPackageBinding[] getOpens() {
 		if (this.openedPackages == null && this.unresolvedOpens != null)
 			resolvePackages();
 		return super.getOpens();
 	}
 
 	private void resolvePackages() {
-		this.exportedPackages = new PackageBinding[this.unresolvedExports.length];
+		this.exportedPackages = new PlainPackageBinding[this.unresolvedExports.length];
 		int count = 0;
 		for (int i = 0; i < this.unresolvedExports.length; i++) {
 			IPackageExport export = this.unresolvedExports[i];
-			PackageBinding declaredPackage = forcedGetExportedPackage(CharOperation.splitOn('.', export.name()));
-			if (declaredPackage != null) {
-				this.exportedPackages[count++] = declaredPackage;
-				if (declaredPackage instanceof SplitPackageBinding)
-					declaredPackage = ((SplitPackageBinding) declaredPackage).getIncarnation(this);
-				if (declaredPackage != null) {
-					declaredPackage.isExported = Boolean.TRUE;
-					recordExportRestrictions(declaredPackage, export.targets());
-				}
-			}
+			// when resolving "exports" in a binary module we simply assume the package must exist,
+			// since this has been checked already when compiling that module.
+			PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', export.name()));
+			this.exportedPackages[count++] = declaredPackage;
+			declaredPackage.isExported = Boolean.TRUE;
+			recordExportRestrictions(declaredPackage, export.targets());
 		}
 		if (count < this.exportedPackages.length)
-			System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[count], 0, count);
+			System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PlainPackageBinding[count], 0, count);
 		
-		this.openedPackages = new PackageBinding[this.unresolvedOpens.length];
+		this.openedPackages = new PlainPackageBinding[this.unresolvedOpens.length];
 		count = 0;
 		for (int i = 0; i < this.unresolvedOpens.length; i++) {
 			IPackageExport opens = this.unresolvedOpens[i];
-			PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', opens.name()));
-			if (declaredPackage != null) {
-				this.openedPackages[count++] = declaredPackage;
-				if (declaredPackage instanceof SplitPackageBinding)
-					declaredPackage = ((SplitPackageBinding) declaredPackage).getIncarnation(this);
-				if (declaredPackage != null) {
-					recordOpensRestrictions(declaredPackage, opens.targets());
-				}
-			} else {
-				// TODO(SHMOD): report incomplete module path?
-			}
+			PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', opens.name()));
+			this.openedPackages[count++] = declaredPackage;
+			recordOpensRestrictions(declaredPackage, opens.targets());
 		}
 		if (count < this.openedPackages.length)
-			System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[count], 0, count);
+			System.arraycopy(this.openedPackages, 0, this.openedPackages = new PlainPackageBinding[count], 0, count);
 	}
-	
-	PackageBinding forcedGetExportedPackage(char[][] compoundName) {
-		// when resolving "exports" in a binary module we simply assume the package must exist,
-		// since this has been checked already when compiling that module.
-		PackageBinding binding = getVisiblePackage(compoundName);
-		if (binding != null)
-			return binding;
-		if (compoundName.length > 1) {
-			PackageBinding parent = forcedGetExportedPackage(CharOperation.subarray(compoundName, 0, compoundName.length-1));
-			binding = new PackageBinding(compoundName, parent, this.environment, this);
-			parent.addPackage(binding, this);
-			return binding;
-		}
-		binding = new PackageBinding(compoundName[0], this.environment, this);
-		addPackage(binding, true);
-		return binding;
+
+	@Override
+	PlainPackageBinding getDeclaredPackage(char[] flatName) {
+		getExports(); // triggers initialization of exported packages into declaredPackages
+		completeIfNeeded(UpdateKind.PACKAGE);
+		return super.getDeclaredPackage(flatName);
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 9b3e8b7..befee9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -44,6 +44,8 @@
  *    Jesper Steen Moller - Contributions for
  *								Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
  *								Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+ *    Sebastian Zarnekow - Contributions for
+ *								bug 544921 - [performance] Poor performance with large source files
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
@@ -63,7 +65,16 @@
 import org.eclipse.jdt.internal.compiler.classfmt.NonNullDefaultAwareTypeAnnotationWalker;
 import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker;
 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
-import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.env.ClassSignature;
+import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
+import org.eclipse.jdt.internal.compiler.env.IBinaryField;
+import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
+import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
 import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -164,6 +175,7 @@
 
 	private ReferenceBinding containerAnnotationType;
 	int defaultNullness = 0;
+	boolean memberTypesSorted = false;
 	public enum ExternalAnnotationStatus {
 		FROM_SOURCE,
 		NOT_EEA_CONFIGURED,
@@ -1658,17 +1670,26 @@
 		return memberType == null ? null : this.environment.createMemberType(memberType, this);
 	}
 
-	for (int i = this.memberTypes.length; --i >= 0;) {
-	    ReferenceBinding memberType = this.memberTypes[i];
-	    if (memberType instanceof UnresolvedReferenceBinding) {
-			char[] name = memberType.sourceName; // source name is qualified with enclosing type name
-			int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
-			if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
-				if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
-					return this.memberTypes[i] = (ReferenceBinding) resolveType(memberType, this.environment, false /* no raw conversion for now */);
-	    } else if (CharOperation.equals(typeName, memberType.sourceName)) {
-	        return memberType;
-	    }
+	ReferenceBinding[] members = maybeSortedMemberTypes();
+	// do not try to binary search while we are still resolving and the array is not necessarily sorted
+	if (!this.memberTypesSorted) {
+		for (int i = members.length; --i >= 0;) {
+		    ReferenceBinding memberType = members[i];
+		    if (memberType instanceof UnresolvedReferenceBinding) {
+				char[] name = memberType.sourceName; // source name is qualified with enclosing type name
+				int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
+				if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
+					if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
+						return members[i] = (ReferenceBinding) resolveType(memberType, this.environment, false /* no raw conversion for now */);
+		    } else if (CharOperation.equals(typeName, memberType.sourceName)) {
+		        return memberType;
+		    }
+		}
+		return null;
+	}
+	int memberTypeIndex = ReferenceBinding.binarySearch(typeName, members);
+	if (memberTypeIndex >= 0) {
+		return members[memberTypeIndex];
 	}
 
 //{ObjectTeams: ROFI: intermediate patch!
@@ -1705,6 +1726,7 @@
 // FIXME(SH): location in file and documentation why/whether needed!
 public static final TypeDeclaration binaryEnclosingTeam = new TypeDeclaration(null);
 // SH}
+
 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 @Override
 public MethodBinding[] getMethods(char[] selector) {
@@ -1930,6 +1952,11 @@
  	if (!isPrototype()) {
 		if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
 			return this.memberTypes;
+		/*
+		 * The members obtained from the prototype are already sorted
+		 * thus we can safely assume that our local copy of the member types
+		 * is sorted, too.
+		 */
 		ReferenceBinding [] members = this.prototype.memberTypes();
 		int memberTypesLength = members == null ? 0 : members.length;
 		if (memberTypesLength > 0) {
@@ -1938,17 +1965,34 @@
 				this.memberTypes[i] = this.environment.createMemberType(members[i], this);
 		}
 		this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
-		return this.memberTypes;	
+		this.memberTypesSorted = true;
+		return this.memberTypes;
 	}
 	
-	if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
-		return this.memberTypes;
-
+	if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0) {
+		return maybeSortedMemberTypes();
+	}
 	for (int i = this.memberTypes.length; --i >= 0;)
 		this.memberTypes[i] = (ReferenceBinding) resolveType(this.memberTypes[i], this.environment, false /* no raw conversion for now */);
 	this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
+	return maybeSortedMemberTypes();
+}
+
+private ReferenceBinding[] maybeSortedMemberTypes() {
+	// do not try to sort while we are still resolving
+	if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) != 0) {
+		return this.memberTypes;
+	}
+	if (!this.memberTypesSorted) {
+		// lazily sort member types
+		int length = this.memberTypes.length;
+		if (length > 1)
+			sortMemberTypes(this.memberTypes, 0, length);
+		this.memberTypesSorted = true;
+	}
 	return this.memberTypes;
 }
+
 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
 @Override
 public MethodBinding[] methods() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index 578fe13..8a47988 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -65,6 +65,7 @@
 	// Shared binding collections
 	public static final ModuleBinding[] NO_MODULES = new ModuleBinding[0];
 	public static final PackageBinding[] NO_PACKAGES = new PackageBinding[0];
+	public static final PlainPackageBinding[] NO_PLAIN_PACKAGES = new PlainPackageBinding[0];
 	public static final TypeBinding[] NO_TYPES = new TypeBinding[0];
 	public static final ReferenceBinding[] NO_REFERENCE_TYPES = new ReferenceBinding[0];
 	public static final TypeBinding[] NO_PARAMETERS = new TypeBinding[0];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
index 444bf63..9117843 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.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
@@ -536,7 +536,7 @@
 
 	@Override
 	public TypeBinding uncapture(Scope scope) {
-		return this.wildcard;
+		return this.wildcard.uncapture(scope);
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 11d5340..0232d10 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -660,18 +660,12 @@
 			char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
 			className[className.length - 1] =
 				CharOperation.concat(className[className.length - 1], this.referenceContext.name, '$');
-			ReferenceBinding existingType = packageBinding.getType0(className[className.length - 1]);
-			if (existingType != null) {
-				if (existingType instanceof UnresolvedReferenceBinding) {
-					// its possible that a BinaryType referenced the member type before its enclosing source type was built
-					// so just replace the unresolved type with a new member type
-				} else {
+			if (packageBinding.hasType0Any(className[className.length - 1])) {
+				// report the error against the parent - its still safe to answer the member type
 //{ObjectTeams: role files are handled below:
-				  if (!isRoleFile)
-// SH}
-					// report the error against the parent - its still safe to answer the member type
-					this.parent.problemReporter().duplicateNestedType(this.referenceContext);
-				}
+			  if (!isRoleFile)
+//SH}
+				this.parent.problemReporter().duplicateNestedType(this.referenceContext);
 			}
 //{ObjectTeams: was assignment; use setter to allow additional setup:
 	/* @original
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index d51f79a..2b4a07e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -16,18 +16,24 @@
  *     Stephan Herrmann - Contribution for
  *								Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
  *								Bug 434570 - Generic type mismatch for parametrized class annotation attribute with inner class
+ *     Sebastian Zarnekow - Contribution for
+ *								Bug 544921 - [performance] Poor performance with large source files
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
 import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -67,17 +73,18 @@
 	public LookupEnvironment environment;
 	public CompilationUnitDeclaration referenceContext;
 	public char[][] currentPackageName;
-	public PackageBinding fPackage;
+	public PlainPackageBinding fPackage;
 	public ImportBinding[] imports;
 	public int importPtr;
 	public HashtableOfObject typeOrPackageCache; // used in Scope.getTypeOrPackage()
 
 	public SourceTypeBinding[] topLevelTypes;
 
-	private CompoundNameVector qualifiedReferences;
-	private SimpleNameVector simpleNameReferences;
-	private SimpleNameVector rootReferences;
-	private ObjectVector referencedTypes;
+	private SortedCompoundNameVector qualifiedReferences;
+	private SortedSimpleNameVector simpleNameReferences;
+	private SortedSimpleNameVector rootReferences;
+	private LinkedHashSet<ReferenceBindingSetWrapper> referencedTypes;
+	private Set<ReferenceBindingSetWrapper> referencedSuperTypesSet;
 	private ObjectVector referencedSuperTypes;
 
 	HashtableOfType constantPoolNameUsage;
@@ -113,16 +120,18 @@
 	this.currentPackageName = unit.currentPackage == null ? CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens;
 
 	if (compilerOptions.produceReferenceInfo) {
-		this.qualifiedReferences = new CompoundNameVector();
-		this.simpleNameReferences = new SimpleNameVector();
-		this.rootReferences = new SimpleNameVector();
-		this.referencedTypes = new ObjectVector();
+		this.qualifiedReferences = new SortedCompoundNameVector();
+		this.simpleNameReferences = new SortedSimpleNameVector();
+		this.rootReferences = new SortedSimpleNameVector();
+		this.referencedTypes = new LinkedHashSet<>();
+		this.referencedSuperTypesSet = new HashSet<>();
 		this.referencedSuperTypes = new ObjectVector();
 	} else {
 		this.qualifiedReferences = null; // used to test if dependencies should be recorded
 		this.simpleNameReferences = null;
 		this.rootReferences = null;
 		this.referencedTypes = null;
+		this.referencedSuperTypesSet = null;
 		this.referencedSuperTypes = null;
 	}
 	// client still needs to assign #environment
@@ -193,7 +202,7 @@
         // ROFI: only create non-team packages here
         // team packages are created in SourceTypeBinding.<init>
 // orig:
-		if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) {
+		if ((this.fPackage = this.environment.createPlainPackage(this.currentPackageName)) == null) {
 // :giro
 			// ROFI: check whether seeming conflict is due to a missing "team" modifier of the package:
 			final Parser parser = Config.getParser();
@@ -261,19 +270,8 @@
 		TypeDeclaration typeDecl = types[i];
 		if (this.environment.root.isProcessingAnnotations && this.environment.isMissingType(typeDecl.name))
 			throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type
-		ReferenceBinding typeBinding = this.fPackage.getType0(typeDecl.name);
-		if (Binding.isValid(typeBinding) && this.fPackage instanceof SplitPackageBinding && !this.environment.module.canAccess(typeBinding.fPackage))
-			typeBinding = null;
 		recordSimpleReference(typeDecl.name); // needed to detect collision cases
-//{ObjectTeams: with role files the assumption below does not hold any more:
-/* orig:
-		if (Binding.isValid(typeBinding) && !(typeBinding instanceof UnresolvedReferenceBinding)) {
-  :giro */
-		if (   Binding.isValid(typeBinding)
-			&& typeBinding != LookupEnvironment.TheNotFoundType
-			&& !(typeBinding instanceof UnresolvedReferenceBinding))
-		{
-// SH}
+		if (this.fPackage.hasType0Any(typeDecl.name)) {
 			// if its an unresolved binding - its fixed up whenever its needed, see UnresolvedReferenceBinding.resolve()
 			if (this.environment.root.isProcessingAnnotations)
 				throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type
@@ -329,6 +327,12 @@
 	// shrink topLevelTypes... only happens if an error was reported
 	if (count != this.topLevelTypes.length)
 		System.arraycopy(this.topLevelTypes, 0, this.topLevelTypes = new SourceTypeBinding[count], 0, count);
+
+	if (this.referenceContext.moduleDeclaration != null) {
+		this.module().completeIfNeeded(IUpdatableModule.UpdateKind.MODULE);
+		this.referenceContext.moduleDeclaration.resolvePackageDirectives(this);
+		this.module().completeIfNeeded(IUpdatableModule.UpdateKind.PACKAGE);
+	}
 }
 //{ObjectTeams: open for Dependencies:
 public
@@ -794,7 +798,6 @@
 public void faultInTypes() {
 	faultInImports();
 	if (this.referenceContext.moduleDeclaration != null) {
-		this.referenceContext.moduleDeclaration.resolvePackageDirectives(this);
 		this.referenceContext.moduleDeclaration.resolveTypeDirectives(this);
 	} else if (this.referenceContext.currentPackage != null) {
 		this.referenceContext.currentPackage.checkPackageConflict(this);
@@ -862,6 +865,11 @@
 
 	ReferenceBinding type;
 	if (binding == null) {
+		if (!module.isUnnamed()) {
+			Binding inaccessible = this.environment.getInaccessibleBinding(compoundName, module);
+			if (inaccessible != null)
+				return inaccessible;
+		}
 		if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
 			return problemType(compoundName, i, null);
 		type = findType(compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage);
@@ -1067,8 +1075,7 @@
 	int length = qualifiedName.length;
 	if (length > 1) {
 		recordRootReference(qualifiedName[0]);
-		while (!this.qualifiedReferences.contains(qualifiedName)) {
-			this.qualifiedReferences.add(qualifiedName);
+		while (this.qualifiedReferences.add(qualifiedName)) {
 			if (length == 2) {
 				recordSimpleReference(qualifiedName[0]);
 				recordSimpleReference(qualifiedName[1]);
@@ -1097,14 +1104,12 @@
 void recordRootReference(char[] simpleName) {
 	if (this.rootReferences == null) return; // not recording dependencies
 
-	if (!this.rootReferences.contains(simpleName))
-		this.rootReferences.add(simpleName);
+	this.rootReferences.add(simpleName);
 }
 void recordSimpleReference(char[] simpleName) {
 	if (this.simpleNameReferences == null) return; // not recording dependencies
 
-	if (!this.simpleNameReferences.contains(simpleName))
-		this.simpleNameReferences.add(simpleName);
+	this.simpleNameReferences.add(simpleName);
 }
 //{ObjectTeams: public for use by CopyInheritance:
 public
@@ -1113,7 +1118,7 @@
 	if (this.referencedSuperTypes == null) return; // not recording dependencies
 
 	ReferenceBinding actualType = typeToRecord(type);
-	if (actualType != null && !this.referencedSuperTypes.containsIdentical(actualType))
+	if (actualType != null && this.referencedSuperTypesSet.add(new ReferenceBindingSetWrapper(actualType)))
 		this.referencedSuperTypes.add(actualType);
 }
 public void recordTypeConversion(TypeBinding superType, TypeBinding subType) {
@@ -1126,8 +1131,8 @@
 	if (this.referencedTypes == null) return; // not recording dependencies
 
 	ReferenceBinding actualType = typeToRecord(type);
-	if (actualType != null && !this.referencedTypes.containsIdentical(actualType))
-		this.referencedTypes.add(actualType);
+	if (actualType != null)
+		this.referencedTypes.add(new ReferenceBindingSetWrapper(actualType));
 }
 void recordTypeReferences(TypeBinding[] types) {
 	if (this.referencedTypes == null) return; // not recording dependencies
@@ -1137,8 +1142,8 @@
 		// No need to record supertypes of method arguments & thrown exceptions, just the compoundName
 		// If a field/method is retrieved from such a type then a separate call does the job
 		ReferenceBinding actualType = typeToRecord(types[i]);
-		if (actualType != null && !this.referencedTypes.containsIdentical(actualType))
-			this.referencedTypes.add(actualType);
+		if (actualType != null)
+			this.referencedTypes.add(new ReferenceBindingSetWrapper(actualType));
 	}
 }
 Binding resolveSingleImport(ImportBinding importBinding, int mask) {
@@ -1173,8 +1178,7 @@
 	// cannot do early since the hierarchy may not be fully resolved
 	for (int i = 0; i < this.referencedSuperTypes.size; i++) { // grows as more types are added
 		ReferenceBinding type = (ReferenceBinding) this.referencedSuperTypes.elementAt(i);
-		if (!this.referencedTypes.containsIdentical(type))
-			this.referencedTypes.add(type);
+		this.referencedTypes.add(new ReferenceBindingSetWrapper(type));
 
 		if (!type.isLocalType()) {
 			ReferenceBinding enclosing = type.enclosingType();
@@ -1190,8 +1194,8 @@
 				recordSuperTypeReference(interfaces[j]);
 	}
 
-	for (int i = 0, l = this.referencedTypes.size; i < l; i++) {
-		ReferenceBinding type = (ReferenceBinding) this.referencedTypes.elementAt(i);
+	for (ReferenceBindingSetWrapper wrapper : this.referencedTypes) {
+		ReferenceBinding type = wrapper.referenceBinding;
 		if (!type.isLocalType())
 			recordQualifiedReference(type.isMemberType()
 				? CharOperation.splitOn('.', type.readableName())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
index c47c724..ccf6562 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
@@ -318,6 +318,8 @@
 				InferenceContext18 innerContext = null;
 				try {
 					innerContext = reference.getInferenceContext((ParameterizedMethodBinding) compileTimeDecl);
+					if (innerContext != null)
+						innerContext.pushBoundsTo(inferenceContext);
 					int innerInferenceKind = determineInferenceKind(compileTimeDecl, argumentTypes, innerContext);
 					inferInvocationApplicability(inferenceContext, original, argumentTypes, original.isConstructor()/*mimic a diamond?*/, innerInferenceKind);
 					if (!inferenceContext.computeB3(reference, r, original))
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 23338e5..4957f3e 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
@@ -489,7 +489,11 @@
 	// ---  not per JLS: emulate how javac passes type bounds from inner to outer: ---
 	/** Not per JLS: push current bounds to outer inference if outer is ready for it. */
 	private void pushBoundsToOuter() {
-		InferenceContext18 outer = this.outerContext;
+		pushBoundsTo(this.outerContext);
+	}
+
+	/** Not per JLS: invent more bubbling up of inner bounds. */
+	public void pushBoundsTo(InferenceContext18 outer) {
 		if (outer != null && outer.stepCompleted >= APPLICABILITY_INFERRED) {
 			boolean deferred = outer.currentInvocation instanceof Invocation; // need to wait till after overload resolution?
 			BoundSet toPush = deferred ? this.currentBounds.copy() : this.currentBounds;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 0acfe58..2e5e3d7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -134,7 +134,7 @@
 	public ModuleBinding UnNamedModule;
 	public ModuleBinding JavaBaseModule;
 	public ModuleBinding module;
-	public PackageBinding defaultPackage;
+	public PlainPackageBinding defaultPackage;
 	/** All visible toplevel packages, i.e. observable packages associated with modules read by the current module. */
 	HashtableOfPackage knownPackages;
 	private int lastCompletedUnitIndex = -1; 	// ROOT_ONLY
@@ -194,6 +194,8 @@
 	 */
 	public boolean suppressImportErrors;			// per module
 
+	public String moduleVersion; 	// ROOT_ONLY
+
 	final static int BUILD_FIELDS_AND_METHODS = 4;
 	final static int BUILD_TYPE_HIERARCHY = 1;
 	final static int CHECK_AND_SET_IMPORTS = 2;
@@ -222,7 +224,7 @@
 	this.typeRequestor = typeRequestor;
 	this.globalOptions = globalOptions;
 	this.problemReporter = problemReporter;
-	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+	this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
 	this.defaultImports = null;
 	this.nameEnvironment = nameEnvironment;
 	this.knownPackages = new HashtableOfPackage();
@@ -247,7 +249,7 @@
 	this.typeRequestor = rootEnv.typeRequestor;
 	this.globalOptions = rootEnv.globalOptions;
 	this.problemReporter = rootEnv.problemReporter;
-	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+	this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
 	this.defaultImports = null;
 	this.nameEnvironment = rootEnv.nameEnvironment;
 	this.knownPackages = new HashtableOfPackage();
@@ -386,8 +388,7 @@
 		if (answerModule != null) {
 			if (!answerPackage.isDeclaredIn(answerModule))
 				continue; // this answer is not reachable via the packageBinding
-			if (answerPackage instanceof SplitPackageBinding)
-				answerPackage = ((SplitPackageBinding) answerPackage).getIncarnation(answerModule);
+			answerPackage = answerPackage.getIncarnation(answerModule);
 		}
 		if (answer.isResolvedBinding()) {
 			candidate = combine(candidate, answer.getResolvedBinding(), clientModule);
@@ -969,7 +970,7 @@
 	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
 		if (this.useModuleSystem) {
 			if (this.module.isUnnamed()) {
-				char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY);
+				char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(new char[][] {constantPoolName[0]}, ModuleBinding.ANY);
 				if (declaringModules != null) {
 					for (char[] mod : declaringModules) {
 						ModuleBinding declaringModule = this.root.getModule(mod);
@@ -982,7 +983,7 @@
 			}
 		}
 		if (packageBinding == null || packageBinding == TheNotFoundPackage) {
-			packageBinding = new PackageBinding(constantPoolName[0], this, this.module);
+			packageBinding = this.module.createDeclaredToplevelPackage(constantPoolName[0]); 
 		}
 		if (isMissing) packageBinding.tagBits |= TagBits.HasMissingType;
 		this.knownPackages.put(constantPoolName[0], packageBinding); // TODO: split?
@@ -993,20 +994,22 @@
 		if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
 			if (this.useModuleSystem) {
 				if (this.module.isUnnamed()) {
-					char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(parent.compoundName, constantPoolName[i], ModuleBinding.ANY);
+					char[][] currentCompoundName = CharOperation.arrayConcat(parent.compoundName, constantPoolName[i]);
+					char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(
+							currentCompoundName, ModuleBinding.ANY);
 					if (declaringModules != null) {
 						for (char[] mod : declaringModules) {
 							ModuleBinding declaringModule = this.root.getModule(mod);
 							if (declaringModule != null)
-								packageBinding = SplitPackageBinding.combine(declaringModule.getPackage(parent.compoundName, constantPoolName[i]), packageBinding, this.module);
+								packageBinding = SplitPackageBinding.combine(declaringModule.getVisiblePackage(currentCompoundName), packageBinding, this.module);
 						}
 					}
 				} else {
-					packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i], true);
+					packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i]);
 				}
 			}
 			if (packageBinding == null || packageBinding == TheNotFoundPackage) {
-				packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this, this.module);
+				packageBinding = this.module.createDeclaredPackage(CharOperation.subarray(constantPoolName, 0, i + 1), parent);
 			}
 			if (isMissing) {
 				packageBinding.tagBits |= TagBits.HasMissingType;
@@ -1314,19 +1317,25 @@
  * 3. Create the method bindings
  */
 public PackageBinding createPackage(char[][] compoundName) {
+	return createPlainPackage(compoundName);	
+}
+public PlainPackageBinding createPlainPackage(char[][] compoundName) {
 //{ObjectTeams: JDT didn't detect collision for toplevel type/package, because default package is weird ;-)
-	// however, for OT/J we must change this to detect matching team package even at top-level.
+// however, for OT/J we must change this to detect matching team package even at top-level.
 	if (compoundName.length == 1) {
 		ReferenceBinding foundType = this.defaultPackage.getType0(compoundName[0]);
 		if (foundType!= null && foundType != TheNotFoundType)
 			return null;
 	}
 // SH}
-	PackageBinding packageBinding = getPackage0(compoundName[0]);
-	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
-		packageBinding = new PackageBinding(compoundName[0], this, this.module);
-		this.knownPackages.put(compoundName[0], packageBinding);
-		if (this.module != null) {
+	PackageBinding packageBinding = this.module.getDeclaredPackage(CharOperation.concatWith(compoundName, '.'));
+	if (packageBinding != null && packageBinding.isValidBinding()) {
+		// restart from the toplevel package to proceed with clash analysis below
+		packageBinding = this.getTopLevelPackage(compoundName[0]);
+	} else {
+		packageBinding = getPackage0(compoundName[0]);
+		if (packageBinding == null || packageBinding == TheNotFoundPackage) {
+			packageBinding = new PlainPackageBinding(compoundName[0], this, this.module);
 			packageBinding = this.module.addPackage(packageBinding, true);
 			this.knownPackages.put(compoundName[0], packageBinding); // update in case of split package
 		}
@@ -1339,8 +1348,7 @@
 		// unless its an unresolved type which is referenced from an inconsistent class file
 		// NOTE: empty packages are not packages according to changes in JLS v2, 7.4.3
 		// so not all types cause collision errors when they're created even though the package did exist
-		ReferenceBinding type = packageBinding.getType0(compoundName[i]);
-		if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
+		if (packageBinding.hasType0Any(compoundName[i]))
 			return null;
 
 		PackageBinding parent = packageBinding;
@@ -1361,21 +1369,18 @@
 					return null;
 				}
 			}
-			if (parent instanceof SplitPackageBinding) {
+			PackageBinding singleParent = parent.getIncarnation(this.module);
+			if (singleParent != parent && singleParent != null) {
 				// parent.getPackage0() may have been too shy, so drill into the split:
-				PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this.module);
-				if (singleParent != null)
-					packageBinding = singleParent.getPackage0(compoundName[i]);
+				packageBinding = singleParent.getPackage0(compoundName[i]);
 			}
 			if (packageBinding == null) {
-				packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module);
+				packageBinding = this.module.createDeclaredPackage(CharOperation.subarray(compoundName, 0, i + 1), parent);
 				packageBinding = parent.addPackage(packageBinding, this.module);
 			}
 		}
 	}
-	if (packageBinding instanceof SplitPackageBinding)
-		packageBinding = ((SplitPackageBinding) packageBinding).getIncarnation(this.module);
-	return packageBinding;
+	return packageBinding.getIncarnation(this.module);
 }
 
 public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, RawTypeBinding rawType) {
@@ -1734,6 +1739,10 @@
 	PackageBinding packageBinding = getPackage0(compoundName[0]);
 	if (packageBinding == null || packageBinding == TheNotFoundPackage)
 		return null;
+	// we should be asking via the correct LE, so peel any SPB at the root:
+	packageBinding = packageBinding.getIncarnation(this.module);
+	if (packageBinding == null || packageBinding == TheNotFoundPackage)
+		return null;
 
 	for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
 		if ((packageBinding = packageBinding.getPackage0Any(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
@@ -1894,23 +1903,17 @@
 * Answer null if the package cannot be found.
 */
 PackageBinding getTopLevelPackage(char[] name) {
+	if (this.useModuleSystem) {
+		return this.module.getTopLevelPackage(name);
+	}
 	PackageBinding packageBinding = getPackage0(name);
 	if (packageBinding != null) {
 		if (packageBinding == TheNotFoundPackage)
 			return null;
 		return packageBinding;
 	}
-	if (this.useModuleSystem) {
-		if (this.module != null)
-			packageBinding = this.module.getTopLevelPackage(name);
-	} else {
-		if (this.nameEnvironment.isPackage(null, name)) {
-			this.knownPackages.put(name, packageBinding = new PackageBinding(name, this, this.module));
-		}
-	}
-	if (packageBinding != null) {
-		if (packageBinding == TheNotFoundPackage)
-			return null;
+	if (this.nameEnvironment.isPackage(null, name)) {
+		this.knownPackages.put(name, packageBinding = this.module.createDeclaredToplevelPackage(name));
 		return packageBinding;
 	}
 
@@ -2461,7 +2464,7 @@
 	this.module = this.UnNamedModule;
 	this.JavaBaseModule = null;
 
-	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+	this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
 	this.defaultImports = null;
 	this.knownPackages = new HashtableOfPackage();
 	this.accessRestrictions = new HashMap(3);
@@ -2592,4 +2595,44 @@
 	}
 	return false;	
 }
+
+public Binding getInaccessibleBinding(char[][] compoundName, ModuleBinding clientModule) {
+	if (this.root != this)
+		return this.root.getInaccessibleBinding(compoundName, clientModule);
+	if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+		IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment;
+		int length = compoundName.length;
+		for (int j=length; j>0; j--) {
+			char[][] candidateName = CharOperation.subarray(compoundName, 0, j);
+			char[][] moduleNames = moduleEnv.getModulesDeclaringPackage(candidateName, ModuleBinding.ANY);
+			if (moduleNames != null) {
+				// in some module a package named candidateName exists, verify observability & inaccessibility:
+				PackageBinding inaccessiblePackage = null;
+				for (char[] moduleName : moduleNames) {
+					if (moduleName == ModuleBinding.UNOBSERVABLE)
+						continue;
+					ModuleBinding mod = getModule(moduleName);
+					if (mod != null) {
+						PackageBinding pack = mod.getVisiblePackage(candidateName);
+						if (pack != null && pack.isValidBinding()) {
+							if (clientModule.canAccess(pack))
+								return null;
+							inaccessiblePackage = pack;
+						}
+					}
+				}
+				if (inaccessiblePackage == null)
+					return null;
+				if (j < length) {
+					// does the package even contain a type of the next name segment?
+					TypeBinding type = inaccessiblePackage.getType(compoundName[j], inaccessiblePackage.enclosingModule);
+					if (type instanceof ReferenceBinding && type.isValidBinding())
+						return new ProblemReferenceBinding(compoundName, (ReferenceBinding) type, ProblemReasons.NotAccessible);
+				}
+				return new ProblemPackageBinding(candidateName, ProblemReasons.NotAccessible, this);
+			}
+		}
+	}
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
index 642fe17..e63a5e2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
@@ -58,6 +58,8 @@
 	public static final char[] ANY = "".toCharArray(); //$NON-NLS-1$
 	/** Module name for package/type lookup that should look into all named modules. */
 	public static final char[] ANY_NAMED = "".toCharArray(); //$NON-NLS-1$
+	/** Module name for an unobservable module */
+	public static final char[] UNOBSERVABLE = "".toCharArray();  //$NON-NLS-1$
 
 	public static class UnNamedModule extends ModuleBinding {
 
@@ -93,6 +95,19 @@
 			return pkg.isDeclaredIn(this) && pkg.hasCompilationUnit(false);
 		}
 		@Override
+		PlainPackageBinding getDeclaredPackage(char[] flatName) {
+			PlainPackageBinding declaredPackage = super.getDeclaredPackage(flatName);
+			if (declaredPackage == null && this.environment.useModuleSystem) {
+				IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
+				char[][] compoundName = CharOperation.splitOn('.', flatName);
+				char[][] declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(compoundName, nameForLookup());
+				if (declaringModuleNames != null && CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
+					declaredPackage = getOrCreateDeclaredPackage(compoundName);
+				}
+			}
+			return declaredPackage;
+		}
+		@Override
 		public boolean isUnnamed() {
 			return true;
 		}
@@ -116,10 +131,10 @@
 	public char[] moduleName;
 	protected ModuleBinding[] requires;
 	protected ModuleBinding[] requiresTransitive;
-	protected PackageBinding[] exportedPackages;
-	private Map<PackageBinding,SimpleSetOfCharArray> exportRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
-	protected PackageBinding[] openedPackages;
-	private Map<PackageBinding,SimpleSetOfCharArray> openRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
+	protected PlainPackageBinding[] exportedPackages;
+	private Map<PlainPackageBinding,SimpleSetOfCharArray> exportRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
+	protected PlainPackageBinding[] openedPackages;
+	private Map<PlainPackageBinding,SimpleSetOfCharArray> openRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
 	protected TypeBinding[] uses;
 	protected TypeBinding[] services;
 	public Map<TypeBinding,TypeBinding[]> implementations;
@@ -133,7 +148,6 @@
 	boolean isAuto = false;
 	private boolean[] isComplete = new boolean[UpdateKind.values().length];
 	private Set<ModuleBinding> transitiveRequires;
-	boolean isPackageLookupActive = false; // to prevent cyclic lookup caused by synthetic reads edges on behalf of auto-modules.
 	SimpleLookupTable storedAnnotations = null;
 
 	/**
@@ -141,8 +155,16 @@
 	 * We consider a package as declared in a module,
 	 * if a compilation unit associated with the module
 	 * declares the package or a subpackage thereof.
+	 * <p>
+	 * A package in this structures is always represented by a {@link PlainPackageBinding},
+	 * as opposed to {@link SplitPackageBinding}, which are only maintained in the trees
+	 * below {@link LookupEnvironment#knownPackages}.
+	 * <p>
+	 * This structure is populated early during compilation with all packages that
+	 * are referenced in exports and opens directives, plus their parent packages.
+	 * </p>
 	 */
-	public HashtableOfPackage declaredPackages;
+	public HashtableOfPackage<PlainPackageBinding> declaredPackages;
 
 	/** Constructor for the unnamed module. */
 	private ModuleBinding(LookupEnvironment env) {
@@ -150,9 +172,9 @@
 		this.environment = env;
 		this.requires = Binding.NO_MODULES;
 		this.requiresTransitive = Binding.NO_MODULES;
-		this.exportedPackages = Binding.NO_PACKAGES;
-		this.openedPackages = Binding.NO_PACKAGES;
-		this.declaredPackages = new HashtableOfPackage(0);
+		this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+		this.openedPackages = Binding.NO_PLAIN_PACKAGES;
+		this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>();
 		Arrays.fill(this.isComplete, true);
 	}
 	/* For error binding and sub class SourceModuleBinding. */
@@ -160,11 +182,11 @@
 		this.moduleName = moduleName;
 		this.requires = Binding.NO_MODULES;
 		this.requiresTransitive = Binding.NO_MODULES;
-		this.exportedPackages = Binding.NO_PACKAGES;
-		this.openedPackages = Binding.NO_PACKAGES;
+		this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+		this.openedPackages = Binding.NO_PLAIN_PACKAGES;
 		this.uses = Binding.NO_TYPES;
 		this.services = Binding.NO_TYPES;
-		this.declaredPackages = new HashtableOfPackage(5);
+		this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>(5);
 	}
 
 	/* For sub class BinaryModuleBinding */
@@ -173,10 +195,10 @@
 		this.requires = Binding.NO_MODULES;
 		this.requiresTransitive = Binding.NO_MODULES;
 		this.environment = new LookupEnvironment(existingEnvironment.root, this);
-		this.declaredPackages = new HashtableOfPackage(5);
+		this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>(5);
 	}
 	
-	public PackageBinding[] getExports() {
+	public PlainPackageBinding[] getExports() {
 		completeIfNeeded(UpdateKind.PACKAGE);
 		return this.exportedPackages;
 	}
@@ -192,7 +214,7 @@
 		}
 		return CharOperation.NO_STRINGS;
 	}
-	public PackageBinding[] getOpens() {
+	public PlainPackageBinding[] getOpens() {
 		completeIfNeeded(UpdateKind.PACKAGE);
 		return this.openedPackages;
 	}
@@ -231,7 +253,7 @@
 		return this.services;
 	}
 
-	private void completeIfNeeded(IUpdatableModule.UpdateKind kind) {
+	void completeIfNeeded(IUpdatableModule.UpdateKind kind) {
 		if (!this.isComplete[kind.ordinal()]) {
 			this.isComplete[kind.ordinal()] = true;
 			if (this.environment.nameEnvironment instanceof IModuleAwareNameEnvironment) {
@@ -257,23 +279,10 @@
 			this.environment.problemReporter.missingModuleAddReads(requiredModuleName);
 			return;
 		}
-		// update known packages:
-		HashtableOfPackage knownPackages = this.environment.knownPackages;
-		for (int i = 0; i < knownPackages.valueTable.length; i++) {
-			PackageBinding packageBinding = knownPackages.valueTable[i];
-			if (packageBinding == null) continue;
-			PackageBinding newBinding = requiredModule.getVisiblePackage(packageBinding.compoundName);
-			newBinding = SplitPackageBinding.combine(newBinding, packageBinding, this);
-			if (packageBinding != newBinding) {
-				knownPackages.valueTable[i] = newBinding;
-				if (this.declaredPackages.containsKey(newBinding.readableName()))
-					this.declaredPackages.put(newBinding.readableName(), newBinding);
-			}
-		}
 	}
 	@Override
 	public void addExports(char[] packageName, char[][] targetModules) {
-		PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', packageName));
+		PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', packageName));
 		if (declaredPackage != null && declaredPackage.isValidBinding())
 			addResolvedExport(declaredPackage, targetModules);
 	}
@@ -293,9 +302,9 @@
 	public char[][] getPackageNamesForClassFile() {
 		if (this.packageNames == null)
 			return null;
-		for (PackageBinding packageBinding : this.exportedPackages)
+		for (PlainPackageBinding packageBinding : this.exportedPackages)
 			this.packageNames.add(packageBinding.readableName());
-		for (PackageBinding packageBinding : this.openedPackages)
+		for (PlainPackageBinding packageBinding : this.openedPackages)
 			this.packageNames.add(packageBinding.readableName());
 		if (this.implementations != null)
 			for (TypeBinding[] types : this.implementations.values())
@@ -305,39 +314,69 @@
 	}
 
 	// ---
+	PlainPackageBinding createDeclaredToplevelPackage(char[] name) {
+		PlainPackageBinding packageBinding = new PlainPackageBinding(name, this.environment, this);
+		this.declaredPackages.put(name, packageBinding);
+		return packageBinding;
+	}
 
-	public void addResolvedExport(PackageBinding declaredPackage, char[][] targetModules) {
-		int len = this.exportedPackages.length;
+	PlainPackageBinding createDeclaredPackage(char[][] compoundName, PackageBinding parent) {
+		PlainPackageBinding packageBinding = new PlainPackageBinding(compoundName, parent, this.environment, this);
+		this.declaredPackages.put(CharOperation.concatWith(compoundName, '.'), packageBinding);
+		return packageBinding;
+	}
+
+	public PlainPackageBinding getOrCreateDeclaredPackage(char[][] compoundName) {
+		char[] flatName = CharOperation.concatWith(compoundName, '.');
+		PlainPackageBinding pkgBinding = this.declaredPackages.get(flatName);
+		if (pkgBinding != null)
+			return pkgBinding;
+		if (compoundName.length > 1) {
+			PlainPackageBinding parent = getOrCreateDeclaredPackage(CharOperation.subarray(compoundName, 0, compoundName.length-1));
+			pkgBinding = new PlainPackageBinding(compoundName, parent, this.environment, this);
+			parent.addPackage(pkgBinding, this);
+		} else {
+			pkgBinding = new PlainPackageBinding(compoundName[0], this.environment, this);
+			PackageBinding problemPackage = this.environment.getPackage0(compoundName[0]);
+			if (problemPackage == LookupEnvironment.TheNotFoundPackage)
+				this.environment.knownPackages.put(compoundName[0], null); // forget TheNotFoundPackage if package was detected late (e.g. with APT in the loop)
+		}
+		this.declaredPackages.put(flatName, pkgBinding);
+		return pkgBinding;
+	}
+
+	public void addResolvedExport(PlainPackageBinding declaredPackage, char[][] targetModules) {
 		if (declaredPackage == null || !declaredPackage.isValidBinding()) {
 			// TODO(SHMOD) use a problem binding (if needed by DOM clients)? See https://bugs.eclipse.org/518794#c13
 			return;
 		}
-		if (len == 0) {
-			this.exportedPackages = new PackageBinding[] { declaredPackage };
+		if (this.exportedPackages == null || this.exportedPackages.length == 0) {
+			this.exportedPackages = new PlainPackageBinding[] { declaredPackage };
 		} else {
-			System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[len+1], 0, len);
+			int len = this.exportedPackages.length;
+			System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PlainPackageBinding[len+1], 0, len);
 			this.exportedPackages[len] = declaredPackage;
 		}
 		declaredPackage.isExported = Boolean.TRUE;
 		recordExportRestrictions(declaredPackage, targetModules);
 	}
 
-	public void addResolvedOpens(PackageBinding declaredPackage, char[][] targetModules) {
+	public void addResolvedOpens(PlainPackageBinding declaredPackage, char[][] targetModules) {
 		int len = this.openedPackages.length;
 		if (declaredPackage == null || !declaredPackage.isValidBinding()) {
 			// TODO(SHMOD) use a problem binding (if needed by DOM clients)? See https://bugs.eclipse.org/518794#c13
 			return;
 		}
 		if (len == 0) {
-			this.openedPackages = new PackageBinding[] { declaredPackage };
+			this.openedPackages = new PlainPackageBinding[] { declaredPackage };
 		} else {
-			System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[len+1], 0, len);
+			System.arraycopy(this.openedPackages, 0, this.openedPackages = new PlainPackageBinding[len+1], 0, len);
 			this.openedPackages[len] = declaredPackage;
 		}
 		recordOpensRestrictions(declaredPackage, targetModules);
 	}
 
-	protected void recordExportRestrictions(PackageBinding exportedPackage, char[][] targetModules) {
+	protected void recordExportRestrictions(PlainPackageBinding exportedPackage, char[][] targetModules) {
 		if (targetModules != null && targetModules.length > 0) {
 			SimpleSetOfCharArray targetModuleSet = null;
 			if (this.exportRestrictions != null) {
@@ -355,7 +394,7 @@
 		}
 	}
 
-	protected void recordOpensRestrictions(PackageBinding openedPackage, char[][] targetModules) {
+	protected void recordOpensRestrictions(PlainPackageBinding openedPackage, char[][] targetModules) {
 		if (targetModules != null && targetModules.length > 0) {
 			SimpleSetOfCharArray targetModuleSet = null;
 			if (this.openRestrictions != null) {
@@ -472,12 +511,7 @@
 	 */
 	public boolean isPackageExportedTo(PackageBinding pkg, ModuleBinding client) {
 		// TODO(SHMOD): cache the result?
-		PackageBinding resolved = null;
-		if (pkg instanceof SplitPackageBinding) {
-			resolved = ((SplitPackageBinding) pkg).getIncarnation(this);
-		} else if (pkg.enclosingModule == this) {
-			resolved = pkg;
-		}
+		PackageBinding resolved = pkg.getIncarnation(this);
 		if (resolved != null) {
 			if (this.isAuto) { // all packages are exported by an automatic module
 				return pkg.enclosingModule == this; // no transitive export
@@ -515,49 +549,28 @@
 	 * </p>
 	 */
 	public PackageBinding getTopLevelPackage(char[] name) {
-		// check caches:
-		PackageBinding binding = this.declaredPackages.get(name);
+		// check cache:
+		PackageBinding binding = this.environment.getPackage0(name);
 		if (binding != null)
-			return binding;
-		binding = this.environment.getPackage0(name);
-		if (binding != null)
-			return binding;
-		binding = getVisiblePackage(null, name, true);
+			return binding == LookupEnvironment.TheNotFoundPackage ? null : binding;
+		binding = getVisiblePackage(null, name);
 		// remember:
 		if (binding != null) {
 			this.environment.knownPackages.put(name, binding);
-			binding = addPackage(binding, false); // no further lookup needed, binding is already complete (split?)
 		} else {
 			this.environment.knownPackages.put(name, LookupEnvironment.TheNotFoundPackage);
 		}
 		return binding;
 	}
 
-	PackageBinding getDeclaredPackage(char[][] parentName, char[] name) {
-		// check caches:
-		char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
-		char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
-		PackageBinding pkg = this.declaredPackages.get(fullFlatName);
-		if (pkg != null)
-			return pkg;
-		PackageBinding parent = parentName.length == 0 ? null : getVisiblePackage(parentName);
-		PackageBinding binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
-		// remember
-		this.declaredPackages.put(fullFlatName, binding);
-		if (parent == null) {
-			this.environment.knownPackages.put(name, binding);
-		}
-		return binding;
+	PlainPackageBinding getDeclaredPackage(char[] flatName) {
+		return this.declaredPackages.get(flatName);
 	}
+
 	// Given parent is visible in this module, see if there is sub package named name visible in this module
-	PackageBinding getVisiblePackage(PackageBinding parent, char[] name, boolean considerRequiredModules) {
-		// check caches:
-		char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName;
-		char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
-		char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
-		PackageBinding pkg = this.declaredPackages.get(fullFlatName);
-		if (pkg != null)
-			return pkg;
+	PackageBinding getVisiblePackage(PackageBinding parent, char[] name) {
+		// check caches in PackageBinding/LookupEnvironment, which contain the full SplitPackageBinding if appropriate:
+		PackageBinding pkg;
 		if (parent != null)
 			pkg = parent.getPackage0(name);
 		else
@@ -569,33 +582,36 @@
 				return addPackage(pkg, false);
 		}
 
-		PackageBinding binding = null;
+		// check cached plain PackageBinding in declaredPackages (which may need combining with siblings):
+		char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName;
+		char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
+		char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
+		PackageBinding binding = this.declaredPackages.get(fullFlatName);
+
 		char[][] declaringModuleNames = null;
-		boolean packageMayBeIncomplete = !considerRequiredModules;
 		if (this.environment.useModuleSystem) {
 			IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
-			declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(parentName, name, nameForLookup());
-			if (declaringModuleNames != null) {
-				if (CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
-					if (parent instanceof SplitPackageBinding) {
-						// parent.getPackage0() may have been too shy, so drill into the split:
-						PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this);
-						if (singleParent != null)
-							binding = singleParent.getPackage0(name);
-					}
-					if (binding == null) {
-						// declared here, not yet known, so create it now:
-						binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
-					}
-				} else if (considerRequiredModules) {
-					// visible but foreign (when current is unnamed or auto):
-					for (char[] declaringModuleName : declaringModuleNames) {
-						ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName);
-						if (declaringModule != null) {
-							if (declaringModule.isPackageLookupActive) {
-								packageMayBeIncomplete = true;
-							} else {
-								PackageBinding declaredPackage = declaringModule.getDeclaredPackage(parentName, name);
+			declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(subPkgCompoundName, nameForLookup());
+			if (binding == null) {
+				if (declaringModuleNames != null) {
+					if (CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
+						if (parent != null) {
+							PackageBinding singleParent = parent.getIncarnation(this);
+							if (singleParent != null && singleParent != parent) {
+								// parent.getPackage0() may have been too shy, so drill into the split:
+								binding = singleParent.getPackage0(name);
+							}
+						}
+						if (binding == null) {
+							// declared here, not yet known, so create it now:
+							binding = new PlainPackageBinding(subPkgCompoundName, parent, this.environment, this);
+						}
+					} else {
+						// visible but foreign (when current is unnamed or auto):
+						for (char[] declaringModuleName : declaringModuleNames) {
+							ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName);
+							if (declaringModule != null) {
+								PlainPackageBinding declaredPackage = declaringModule.getDeclaredPackage(fullFlatName);
 								if (declaredPackage != null) {
 									// don't add foreign package to 'parent' (below), but to its own parent:
 									if (declaredPackage.parent != null)
@@ -611,18 +627,15 @@
 			}
 		} else {
 			if (this.environment.nameEnvironment.isPackage(parentName, name))
-				binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
+				binding = new PlainPackageBinding(subPkgCompoundName, parent, this.environment, this);
 		}
 
 		// enrich with split-siblings from visible modules:
-		if (considerRequiredModules) {
-			if (parent != null && binding != null)
-				parent.addPackage(binding, this); // preliminarily add to avoid creating duplicates, will be updated below
-			binding = combineWithPackagesFromOtherRelevantModules(binding, subPkgCompoundName, declaringModuleNames);
-		}
+		if (parent != null && binding != null)
+			parent.addPackage(binding, this); // preliminarily add to avoid creating duplicates, will be updated below
+		binding = combineWithPackagesFromOtherRelevantModules(binding, subPkgCompoundName, declaringModuleNames);
 		if (binding == null || !binding.isValidBinding()) {
 			if (parent != null
-					&& !packageMayBeIncomplete  // don't remember package that may still lack some siblings
 					&& !(parent instanceof SplitPackageBinding)) // don't store problem into SPB, because from different focus things may look differently
 			{
 				if (binding == null) {
@@ -639,8 +652,6 @@
 		} else if (parent != null) {
 			binding = parent.addPackage(binding, this);
 		}
-		if (packageMayBeIncomplete)
-			return binding;
 		return addPackage(binding, false);
 	}
 
@@ -653,21 +664,18 @@
 	 * </p>
 	 */
 	public PackageBinding getVisiblePackage(char[][] qualifiedPackageName) {
-		return getVisiblePackage(qualifiedPackageName, true);
-	}
-	PackageBinding getVisiblePackage(char[][] qualifiedPackageName, boolean considerRequiredModules) {
 		if (qualifiedPackageName == null || qualifiedPackageName.length == 0) {
 			return this.environment.defaultPackage;
 		}
 
 		PackageBinding parent = getTopLevelPackage(qualifiedPackageName[0]);
-		if (parent == null || parent == LookupEnvironment.TheNotFoundPackage)
+		if (parent == null)
 			return null;
 
 		// check each sub package
 		for (int i = 1; i < qualifiedPackageName.length; i++) {
-			PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i], considerRequiredModules); 
-			if (binding == null || binding == LookupEnvironment.TheNotFoundPackage) {
+			PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i]); 
+			if (binding == null) {
 				return null;
 			}
 			parent = binding;
@@ -676,30 +684,6 @@
 	}
 
 	/**
-	 * Answer a package, that is a member named <em>packageName</em> of the parent package
-	 * named <em>parentPackageName</em>.
-	 * Considers all packages that are visible to the current module,
-	 * i.e., we consider locally declared packages and packages in all modules
-	 * read by the current module.
-	 * Accessibility (via package exports) is <strong>not</strong> checked.
-	 */
-	public PackageBinding getPackage(char[][] parentPackageName, char[] packageName) {
-		// Returns a package binding if there exists such a package in the context of this module and it is observable
-		// A package is observable if it is declared in this module or it is exported by some required module
-		if (parentPackageName == null || parentPackageName.length == 0) {
-			return getVisiblePackage(null, packageName, true);
-		}
-		PackageBinding binding = null;
-		PackageBinding parent = getVisiblePackage(parentPackageName);
-		if (parent != null && parent != LookupEnvironment.TheNotFoundPackage) {
-			binding = getVisiblePackage(parent, packageName, true);
-		}
-		if (binding != null)
-			return addPackage(binding, false);
-		return null;
-	}
-	
-	/**
 	 * Check if the given package is declared in this module,
 	 * and if so, remember this fact for later.
 	 * The package can be a {@code SplitPackageBinding} in which case
@@ -716,11 +700,11 @@
 				char[][] declaringModuleNames = null;
 				if (isUnnamed()) {
 					IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
-					declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(null, packageName, ANY);
+					declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(new char[][] {packageName}, ANY);
 				}
 				packageBinding = combineWithPackagesFromOtherRelevantModules(packageBinding, packageBinding.compoundName, declaringModuleNames);
 			}
-			this.declaredPackages.put(packageName, packageBinding);
+			this.declaredPackages.put(packageName, packageBinding.getIncarnation(this));
 			if (packageBinding.parent == null) {
 				this.environment.knownPackages.put(packageName, packageBinding);
 			}
@@ -729,23 +713,11 @@
 	}
 	
 	private PackageBinding combineWithPackagesFromOtherRelevantModules(PackageBinding currentBinding, char[][] compoundName, char[][] declaringModuleNames) {
-		boolean save = this.isPackageLookupActive;
-		this.isPackageLookupActive = true;
-		try {
-			char[] singleName = compoundName[compoundName.length-1];
-			PackageBinding parent = currentBinding != null ? currentBinding.parent : null;
-			for (ModuleBinding moduleBinding : otherRelevantModules(declaringModuleNames)) {
-				if (!moduleBinding.isPackageLookupActive) {
-					PackageBinding nextBinding = parent != null 
-							? moduleBinding.getVisiblePackage(parent, singleName, false)
-							: moduleBinding.getVisiblePackage(compoundName, false);
-					currentBinding = SplitPackageBinding.combine(nextBinding, currentBinding, this);
-				}
-			}
-			return currentBinding;
-		} finally {
-			this.isPackageLookupActive = save;
+		for (ModuleBinding moduleBinding : otherRelevantModules(declaringModuleNames)) {
+			PlainPackageBinding nextBinding = moduleBinding.getDeclaredPackage(CharOperation.concatWith(compoundName, '.'));
+			currentBinding = SplitPackageBinding.combine(nextBinding, currentBinding, this);
 		}
+		return currentBinding;
 	}
 
 	List<ModuleBinding> otherRelevantModules(char[][] declaringModuleNames) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index 9d8420d..c853d94 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -33,7 +33,7 @@
  *
  * What: make addNotFoundType visible to sub class TeamPackageBinding
  */
-public class PackageBinding extends Binding implements TypeConstants {
+public abstract class PackageBinding extends Binding implements TypeConstants {
 	public long tagBits = 0; // See values in the interface TagBits below
 
 	public char[][] compoundName;
@@ -43,7 +43,7 @@
 	/** Types in this map are either uniquely visible in the current module or ProblemReferenceBindings. */
 	public HashtableOfType knownTypes;
 	/** All visible member packages, i.e. observable packages associated with modules read by the current module. */
-	HashtableOfPackage knownPackages;
+	HashtableOfPackage<PackageBinding> knownPackages;
 
 	// code representing the default that has been defined for this package (using @NonNullByDefault)
 	// one of Binding.{NO_NULL_DEFAULT,NULL_UNSPECIFIED_BY_DEFAULT,NONNULL_BY_DEFAULT}
@@ -54,12 +54,12 @@
 	/** Is this package exported from its module? NB: to query this property use {@link #isExported()} to ensure initialization. */
 	Boolean isExported;
 
-protected PackageBinding() {
+protected PackageBinding(char[][] compoundName, LookupEnvironment environment) {
 	// for creating problem package
+	this.compoundName = compoundName;
+	this.environment = environment;
 }
-public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment, ModuleBinding enclosingModule) {
-	this(new char[][] {topLevelPackageName}, null, environment, enclosingModule);
-}
+
 /* Create a normal package.
 */
 public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment, ModuleBinding enclosingModule) {
@@ -67,7 +67,7 @@
 	this.parent = parent;
 	this.environment = environment;
 	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
-	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
+	this.knownPackages = new HashtableOfPackage<PackageBinding>(3); // sub-package counts are typically 0-3
 	
 	if (compoundName != CharOperation.NO_CHAR_CHAR)
 		checkIfNullAnnotationPackage();
@@ -81,9 +81,6 @@
 		throw new IllegalStateException("Package should have an enclosing module"); //$NON-NLS-1$
 }
 
-public PackageBinding(LookupEnvironment environment) {
-	this(CharOperation.NO_CHAR_CHAR, null, environment, environment.module);
-}
 protected void addNotFoundPackage(char[] simpleName) {
 	if (!this.environment.suppressImportErrors)
 		this.knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
@@ -153,7 +150,7 @@
 }
 protected PackageBinding findPackage(char[] name, ModuleBinding module) {
 	// delegate to the module to consider the module graph:
-	return module.getPackage(this.compoundName, name);
+	return module.getVisiblePackage(CharOperation.arrayConcat(this.compoundName, name));
 }
 /* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
 * Answer null if it could not be resolved.
@@ -236,6 +233,17 @@
 		return null;
 	return this.knownTypes.get(name);
 }
+
+/**
+ * Test if this package (or any of its incarnations in case of a SplitPackageBinding) has recorded
+ * an actual, resolved type of the given name (based on answers from getType0()).
+ * Useful for clash detection.
+ */
+boolean hasType0Any(char[] name) {
+	ReferenceBinding type0 = getType0(name);
+	return type0 != null && type0 != LookupEnvironment.TheNotFoundType && !(type0 instanceof UnresolvedReferenceBinding);
+}
+
 /* Answer the package or type named name; ask the oracle if it is not in the cache.
 * Answer null if it could not be resolved.
 *
@@ -268,8 +276,8 @@
 
 	PackageBinding packageBinding = getPackage0(name);
 	if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) {
-		if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
-			return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+		if (!splitPackageAllowed) {
+			return packageBinding.getVisibleFor(mod, false);
 		}
 		return packageBinding;
 	}
@@ -294,8 +302,8 @@
 
 	if (packageBinding == null) { // have not looked for it before
 		if ((packageBinding = findPackage(name, mod)) != null) {
-			if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
-				return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+			if (!splitPackageAllowed) {
+				return packageBinding.getVisibleFor(mod, false);
 			}
 			return packageBinding;
 		}
@@ -537,15 +545,23 @@
 }
 /**
  * If this package is uniquely visible to 'module' return a plain PackageBinding.
- * In case of a conflict between a local package and foreign package
- * the plain local package is returned, because this conflict will more
- * appropriately be reported against the package declaration, not its references.
+ * In case of a conflict between a local package and foreign package flag <b>preferLocal</b>
+ * will select the behavior:
+ * <ul>
+ * <li>if {@code true} the plain local package is returned, because this conflict will more
+ * appropriately be reported against the package declaration, not its references.</li>
+ * <li>if {@code false} a conflict local vs. foreign will be treated just like any other conflict,
+ * see next.</li>
+ * </ul>
  * In case of multiple accessible foreign packages a SplitPackageBinding is returned
  * to indicate a conflict.
  */
 public PackageBinding getVisibleFor(ModuleBinding module, boolean preferLocal) {
 	return this;
 }
+
+public abstract PlainPackageBinding getIncarnation(ModuleBinding moduleBinding);
+
 public boolean hasCompilationUnit(boolean checkCUs) {
 	if (this.knownTypes != null) {
 		for (ReferenceBinding knownType : this.knownTypes.valueTable) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 0d3ebbb..7ab09a4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -1163,6 +1163,8 @@
 	public ReferenceBinding[] memberTypes() {
 		if (this.memberTypes == null) {
 			try {
+				// the originalMemberTypes are already sorted by name so there
+				// is no need to sort again in our copy - names are not affected by type parameters
 				ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
 				int length = originalMemberTypes.length;
 				ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java
new file mode 100644
index 0000000..97ea1a2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2019 GK Software SE, and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/** A package binding that is known not to be a {@link SplitPackageBinding}. */
+public class PlainPackageBinding extends PackageBinding {
+
+	/** Create a toplevel package. */
+	public PlainPackageBinding(char[] topLevelPackageName, LookupEnvironment environment, ModuleBinding enclosingModule) {
+		super(new char[][] {topLevelPackageName}, null, environment, enclosingModule);
+	}
+
+	/** Create a default package. */
+	public PlainPackageBinding(LookupEnvironment environment) {
+		super(CharOperation.NO_CHAR_CHAR, null, environment, environment.module);
+	}
+
+	/** Create a normal package. */
+	public PlainPackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment, ModuleBinding enclosingModule) {
+		super(compoundName, parent, environment, enclosingModule);
+	}
+
+	protected PlainPackageBinding(char[][] compoundName, LookupEnvironment environment) {
+		// for problem bindings
+		super(compoundName, environment);
+	}
+
+	@Override
+	public PlainPackageBinding getIncarnation(ModuleBinding moduleBinding) {
+		if (this.enclosingModule == moduleBinding)
+			return this;
+		return null;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
index b6e6feb..3018681 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 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
@@ -14,14 +14,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
-public class ProblemPackageBinding extends PackageBinding {
+public class ProblemPackageBinding extends PlainPackageBinding {
 	private int problemId;
 // NOTE: must only answer the subset of the name related to the problem
 
 ProblemPackageBinding(char[][] compoundName, int problemId, LookupEnvironment environment) {
-	this.compoundName = compoundName;
+	super(compoundName, environment);
 	this.problemId = problemId;
-	this.environment = environment;
 }
 //{ObjectTeams: accessible for OTClassScope:
 public
@@ -29,11 +28,11 @@
 ProblemPackageBinding(char[] name, int problemId, LookupEnvironment environment) {
 	this(new char[][] {name}, problemId, environment);
 }
-/* API
-* Answer the problem id associated with the receiver.
-* NoError if the receiver is a valid binding.
-*/
-
+/**
+ * API
+ * Answer the problem id associated with the receiver.
+ * NoError if the receiver is a valid binding.
+ */
 @Override
 public final int problemId() {
 	return this.problemId;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 2205a56..1f7418b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.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
@@ -49,6 +49,8 @@
  *                              bug 386692 - Missing "unused" warning on "autowired" fields
  *     Pierre-Yves B. <pyvesdev@gmail.com> - Contribution for
  *                              bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource
+ *     Sebastian Zarnekow - Contributions for
+ *								bug 544921 - [performance] Poor performance with large source files
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
@@ -154,9 +156,7 @@
 	};
 	private static final Comparator<MethodBinding> METHOD_COMPARATOR = new Comparator<MethodBinding>() {
 		@Override
-		public int compare(MethodBinding o1, MethodBinding o2) {
-			MethodBinding m1 = o1;
-			MethodBinding m2 = o2;
+		public int compare(MethodBinding m1, MethodBinding m2) {
 			char[] s1 = m1.selector;
 			char[] s2 = m2.selector;
 			int c = ReferenceBinding.compare(s1, s2, s1.length, s2.length);
@@ -392,6 +392,19 @@
 // SH}
 
 /**
+ * Sort the member types using a quicksort
+ */
+static void sortMemberTypes(ReferenceBinding[] sortedMemberTypes, int left, int right) {
+	Arrays.sort(sortedMemberTypes, left, right, BASIC_MEMBER_TYPES_COMPARATOR);
+}
+
+static final Comparator<ReferenceBinding> BASIC_MEMBER_TYPES_COMPARATOR = (ReferenceBinding o1, ReferenceBinding o2) -> {
+	char[] n1 = o1.sourceName;
+	char[] n2 = o2.sourceName;
+	return ReferenceBinding.compare(n1, n2, n1.length, n2.length);
+};
+
+/**
  * Return the array of resolvable fields (resilience)
  */
 public FieldBinding[] availableFields() {
@@ -1246,11 +1259,16 @@
 	return this.fileName;
 }
 
+/**
+ * Find the member type with the given simple typeName. Benefits from the fact that
+ * the array of {@link #memberTypes()} is sorted.
+ */
 public ReferenceBinding getMemberType(char[] typeName) {
 	ReferenceBinding[] memberTypes = memberTypes();
-	for (int i = memberTypes.length; --i >= 0;)
-		if (CharOperation.equals(memberTypes[i].sourceName, typeName))
-			return memberTypes[i];
+	int memberTypeIndex = binarySearch(typeName, memberTypes);
+	if (memberTypeIndex >= 0) {
+		return memberTypes[memberTypeIndex];
+	}
 	return null;
 }
 //{ObjectTeams: new utility function
@@ -1267,6 +1285,29 @@
 }
 // SH}
 
+static int binarySearch(char[] name, ReferenceBinding[] sortedMemberTypes) {
+	if (sortedMemberTypes == null)
+		return -1;
+	int max = sortedMemberTypes.length;
+	if (max == 0)
+		return -1;
+	int left = 0, right = max - 1, nameLength = name.length;
+	int mid = 0;
+	char[] midName;
+	while (left <= right) {
+		mid = left + (right - left) /2;
+		int compare = compare(name, midName = sortedMemberTypes[mid].sourceName, nameLength, midName.length);
+		if (compare < 0) {
+			right = mid-1;
+		} else if (compare > 0) {
+			left = mid+1;
+		} else {
+			return mid;
+		}
+	}
+	return -1;
+}
+
 @Override
 public MethodBinding[] getMethods(char[] selector) {
 	return Binding.NO_METHODS;
@@ -1389,6 +1430,10 @@
 		: CharOperation.hashCode(this.compoundName[this.compoundName.length - 1]);
 }
 
+final int identityHashCode() {
+	return super.hashCode();
+}
+
 /**
  * Returns true if the two types have an incompatible common supertype,
  * e.g. List<String> and List<Integer>
@@ -2079,6 +2124,9 @@
 	return false;
 }
 
+/**
+ * Returns the member types of this type sorted by simple name.
+ */
 @Override
 public ReferenceBinding[] memberTypes() {
 	return Binding.NO_MEMBER_TYPES;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBindingSetWrapper.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBindingSetWrapper.java
new file mode 100644
index 0000000..e411ed1
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBindingSetWrapper.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+/**
+ * Defines a wrapper type for {@link ReferenceBinding} and provides proper hashCode() and equals() based on the wrapped
+ * {@link ReferenceBinding} object identity comparison.
+ * <p>
+ * Note: {@link ReferenceBinding} defines a hashCode() which is not consistent with the respective equals()
+ * implementation).
+ */
+final class ReferenceBindingSetWrapper {
+
+	final ReferenceBinding referenceBinding;
+	private int hashCode;
+
+	ReferenceBindingSetWrapper(ReferenceBinding referenceBinding) {
+		this.referenceBinding = referenceBinding;
+		this.hashCode = referenceBinding.identityHashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (obj instanceof ReferenceBindingSetWrapper) {
+			ReferenceBindingSetWrapper other = (ReferenceBindingSetWrapper) obj;
+			return identityEqual(this.referenceBinding, other.referenceBinding);
+		}
+		return false;
+	}
+
+	private static boolean identityEqual(Object o1, Object o2) {
+		return o1 == o2;
+	}
+
+	@Override
+	public int hashCode() {
+		return this.hashCode;
+	}
+
+	@Override
+	public String toString() {
+		return this.referenceBinding.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedCompoundNameVector.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedCompoundNameVector.java
new file mode 100644
index 0000000..f6d2a7d
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedCompoundNameVector.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Sebastian Zarnekow and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Sebastian Zarnekow - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Arrays;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.util.SortedCharArrays;
+
+/**
+ * Sorted and simplified version of previously existed CompoundNameVector
+ */
+final class SortedCompoundNameVector {
+
+	static int INITIAL_SIZE = 10;
+
+	int size;
+	char[][][] elements;
+
+	public SortedCompoundNameVector() {
+		this.size = 0;
+		this.elements = new char[INITIAL_SIZE][][];
+	}
+
+	public boolean add(char[][] newElement) {
+		int idx = Arrays.binarySearch(this.elements, 0, this.size, newElement, SortedCharArrays.CHAR_CHAR_ARR_COMPARATOR);
+		if (idx < 0) {
+			this.elements = SortedCharArrays.insertIntoArray(
+					this.elements,
+					this.size < this.elements.length ? this.elements : new char[this.elements.length * 2][][],
+					newElement,
+					-(idx + 1),
+					this.size++);
+			return true;
+		}
+		return false;
+	}
+
+	public char[][] elementAt(int index) {
+		return this.elements[index];
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder buffer = new StringBuilder();
+		for (int i = 0; i < this.size; i++) {
+			buffer.append(CharOperation.toString(this.elements[i])).append("\n"); //$NON-NLS-1$
+		}
+		return buffer.toString();
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedSimpleNameVector.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedSimpleNameVector.java
new file mode 100644
index 0000000..2cd0179
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SortedSimpleNameVector.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Sebastian Zarnekow and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Sebastian Zarnekow - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Arrays;
+
+import org.eclipse.jdt.internal.compiler.util.SortedCharArrays;
+
+/**
+ * Sorted and simplified version of previously existed SimpleNameVector
+ */
+final class SortedSimpleNameVector {
+
+	static int INITIAL_SIZE = 10;
+
+	int size;
+	char[][] elements;
+
+	public SortedSimpleNameVector() {
+		this.size = 0;
+		this.elements = new char[INITIAL_SIZE][];
+	}
+
+	public boolean add(char[] newElement) {
+		int idx = Arrays.binarySearch(this.elements, 0, this.size, newElement, SortedCharArrays.CHAR_ARR_COMPARATOR);
+		if (idx < 0) {
+			this.elements = SortedCharArrays.insertIntoArray(
+					this.elements,
+					this.size < this.elements.length ? this.elements : new char[this.elements.length * 2][],
+					newElement,
+					-(idx + 1),
+					this.size++);
+			return true;
+		}
+		return false;
+	}
+
+	public char[] elementAt(int index) {
+		return this.elements[index];
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder buffer = new StringBuilder();
+		for (int i = 0; i < this.size; i++) {
+			buffer.append(this.elements[i]).append("\n"); //$NON-NLS-1$
+		}
+		return buffer.toString();
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
index ee5fd9a..76d92b2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
@@ -119,14 +119,14 @@
 	}
 
 	@Override
-	public PackageBinding[] getExports() {
+	public PlainPackageBinding[] getExports() {
 		// don't rely on "if (this.exportedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded()
 		this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope);
 		return super.getExports();
 	}
 
 	@Override
-	public PackageBinding[] getOpens() {
+	public PlainPackageBinding[] getOpens() {
 		// don't rely on "if (this.openedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded()
 		this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope);
 		return super.getOpens();
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 c2a6523..e90c7dd 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
@@ -50,6 +50,8 @@
  *     							bug 415269 - NonNullByDefault is not always inherited to nested classes
  *      Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
  *                          	Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
+ *      Sebastian Zarnekow - Contributions for
+ *								bug 544921 - [performance] Poor performance with large source files
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
@@ -189,6 +191,7 @@
 	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
 
 	public int defaultNullness;
+	boolean memberTypesSorted = false;
 	private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
 	private ReferenceBinding containerAnnotationType = null;
 
@@ -2070,7 +2073,9 @@
 public ReferenceBinding[] memberTypes() {
 	if (!isPrototype()) {
 		if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
-			return this.memberTypes;
+			return sortedMemberTypes();
+		// members obtained from the prototype are already sorted so it is safe
+		// to set the sorted flag here immediately.
 		ReferenceBinding [] members = this.memberTypes = this.prototype.memberTypes();
 		int membersLength = members == null ? 0 : members.length;
 		this.memberTypes = new ReferenceBinding[membersLength];
@@ -2078,6 +2083,18 @@
 			this.memberTypes[i] = this.environment.createMemberType(members[i], this);
 		}
 		this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
+		this.memberTypesSorted = true;
+	}
+	return sortedMemberTypes();
+}
+
+private ReferenceBinding[] sortedMemberTypes() {
+	if (!this.memberTypesSorted) {
+		// lazily sort member types
+		int length = this.memberTypes.length;
+		if (length > 1)
+			sortMemberTypes(this.memberTypes, 0, length);
+		this.memberTypesSorted = true;
 	}
 	return this.memberTypes;
 }
@@ -3094,6 +3111,7 @@
 			annotatedType.memberTypes(); // recompute.
 		}
 	}
+	sortedMemberTypes();
 	return this.memberTypes;
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
index 8bb5266..ee04403 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 GK Software SE, and others.
+ * Copyright (c) 2017, 2019 GK Software SE, and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -21,7 +21,7 @@
 
 public class SplitPackageBinding extends PackageBinding {
 	Set<ModuleBinding> declaringModules;
-	public Set<PackageBinding> incarnations;
+	public Set<PlainPackageBinding> incarnations;
 	
 	/**
 	 * Combine two potential package bindings, answering either the better of those if the other has a problem,
@@ -71,14 +71,14 @@
 		if (packageBinding instanceof SplitPackageBinding) {
 			SplitPackageBinding split = (SplitPackageBinding) packageBinding;
 			this.declaringModules.addAll(split.declaringModules);
-			for(PackageBinding incarnation: split.incarnations) {
+			for(PlainPackageBinding incarnation: split.incarnations) {
 				if(this.incarnations.add(incarnation)) {
 					incarnation.addWrappingSplitPackageBinding(this);
 				}
 			}
-		} else {
+		} else if (packageBinding instanceof PlainPackageBinding) {
 			this.declaringModules.add(packageBinding.enclosingModule);
-			if(this.incarnations.add(packageBinding)) {
+			if(this.incarnations.add((PlainPackageBinding) packageBinding)) {
 				packageBinding.addWrappingSplitPackageBinding(this);
 			}
 		}
@@ -92,31 +92,32 @@
 		PackageBinding visible = this.knownPackages.get(simpleName);
 		visible = SplitPackageBinding.combine(element, visible, this.enclosingModule);
 		this.knownPackages.put(simpleName, visible);
-		PackageBinding incarnation = getIncarnation(element.enclosingModule);
-		if (incarnation != null)
-			incarnation.addPackage(element, module);
+
+		// also record the PPB's as parent-child:
+		PlainPackageBinding incarnation = getIncarnation(element.enclosingModule);
+		if (incarnation != null) {
+			// avoid adding an SPB as a child of a PPB:
+			PlainPackageBinding elementIncarnation = element.getIncarnation(element.enclosingModule);
+			if (elementIncarnation != null)
+				incarnation.addPackage(elementIncarnation, module);
+		}
 		return element;
 	}
 
 	PackageBinding combineWithSiblings(PackageBinding childPackage, char[] name, ModuleBinding module) {
-		ModuleBinding primaryModule = childPackage != null ? childPackage.enclosingModule : this.enclosingModule;
+		ModuleBinding primaryModule = childPackage.enclosingModule;
 		// see if other incarnations contribute to the child package, too:
-		boolean activeSave = primaryModule.isPackageLookupActive;
-		primaryModule.isPackageLookupActive = true;
-		try {
-			for (PackageBinding incarnation :  this.incarnations) {
-				ModuleBinding moduleBinding = incarnation.enclosingModule;
-				if (moduleBinding == module)
-					continue;
-				if (childPackage.isDeclaredIn(moduleBinding))
-					continue;
-				PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name, false);
-				childPackage = combine(next, childPackage, primaryModule);
-			}
-			return childPackage;
-		} finally {
-			primaryModule.isPackageLookupActive = activeSave;
+		char[] flatName = CharOperation.concatWith(childPackage.compoundName, '.');
+		for (PackageBinding incarnation :  this.incarnations) {
+			ModuleBinding moduleBinding = incarnation.enclosingModule;
+			if (moduleBinding == module)
+				continue;
+			if (childPackage.isDeclaredIn(moduleBinding))
+				continue;
+			PlainPackageBinding next = moduleBinding.getDeclaredPackage(flatName);
+			childPackage = combine(next, childPackage, primaryModule);
 		}
+		return childPackage;
 	}
 	
 	@Override
@@ -162,9 +163,10 @@
 
 	@Override
 	protected PackageBinding findPackage(char[] name, ModuleBinding module) {
+		char[][] subpackageCompoundName = CharOperation.arrayConcat(this.compoundName, name);
 		Set<PackageBinding> candidates = new HashSet<>();
 		for (ModuleBinding candidateModule : this.declaringModules) {
-			PackageBinding candidate = super.findPackage(name, candidateModule);
+			PackageBinding candidate = candidateModule.getVisiblePackage(subpackageCompoundName);
 			if (candidate != null
 					&& candidate != LookupEnvironment.TheNotFoundPackage
 					&& ((candidate.tagBits & TagBits.HasMissingType) == 0))
@@ -190,8 +192,9 @@
 		return result;
 	}
 
-	public PackageBinding getIncarnation(ModuleBinding requestedModule) {
-		for (PackageBinding incarnation : this.incarnations) {
+	@Override
+	public PlainPackageBinding getIncarnation(ModuleBinding requestedModule) {
+		for (PlainPackageBinding incarnation : this.incarnations) {
 			if (incarnation.enclosingModule == requestedModule)
 				return incarnation;
 		}
@@ -209,27 +212,15 @@
 	}
 
 	@Override
-	ReferenceBinding getType0(char[] name) {
-		ReferenceBinding knownType = super.getType0(name);
-		if (knownType != null && !(knownType instanceof UnresolvedReferenceBinding))
-			return knownType;
+	boolean hasType0Any(char[] name) {
+		if (super.hasType0Any(name))
+			return true;
 
-		ReferenceBinding candidate = null;
 		for (PackageBinding incarnation : this.incarnations) {
-			ReferenceBinding next = incarnation.getType0(name);
-			if (next != null) {
-				if (next.isValidBinding() && !(knownType instanceof UnresolvedReferenceBinding)) {
-					if (candidate != null)
-						return null; // unable to disambiguate without a module context
-					candidate = next;
-				}
-			}
+			if (incarnation.hasType0Any(name))
+				return true;
 		}
-		if (candidate != null) {
-			addType(candidate);
-		}
-		
-		return candidate;
+		return false;
 	}
 
 	/** Similar to getType0() but now we have a module and can ask the specific incarnation! */
@@ -268,20 +259,21 @@
 	@Override
 	public PackageBinding getVisibleFor(ModuleBinding clientModule, boolean preferLocal) {
 		int visibleCount = 0;
-		PackageBinding unique = null;
-		for (PackageBinding incarnation : this.incarnations) {
+		PlainPackageBinding unique = null;
+		for (PlainPackageBinding incarnation : this.incarnations) {
 			if (incarnation.hasCompilationUnit(false)) {
 				if (preferLocal && incarnation.enclosingModule == clientModule) {
 					return incarnation;
 				} else {
 					if (clientModule.canAccess(incarnation)) {
-						if (++visibleCount > 1)
-							return this;
+						visibleCount++;
 						unique = incarnation;
 					}
 				}
 			}
 		}
+		if (visibleCount > 1)
+			return this; // conflict, return split
 		return unique;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
index 2f5a43d..bcfb172 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -135,9 +135,7 @@
 		try {
 			allBounds[0] = (ReferenceBinding) this.bound;
 			System.arraycopy(this.otherBounds, 0, allBounds, 1, this.otherBounds.length);
-		} catch (ClassCastException cce) {
-			return this.bound;
-		} catch (ArrayStoreException ase) {
+		} catch (ClassCastException | ArrayStoreException ase) {
 			return this.bound;
 		}
 		return this.environment.createIntersectionType18(allBounds);
@@ -729,9 +727,7 @@
     		try {
     			allBounds[0] = (ReferenceBinding) this.bound;
     			System.arraycopy(this.otherBounds, 0, allBounds, 1, this.otherBounds.length);
-    		} catch (ClassCastException cce) {
-    			return null;
-    		} catch (ArrayStoreException ase) {
+    		} catch (ClassCastException | ArrayStoreException ase) {
     			return null;
     		}
     		return allBounds;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
index 7d515c7..c915819 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
@@ -106,7 +106,8 @@
 
 	protected AbstractCommentParser(Parser sourceParser) {
 		this.sourceParser = sourceParser;
-		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/);
+		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/,
+				sourceParser != null ? this.sourceParser.options.enablePreviewFeatures : false);
 		this.identifierStack = new char[20][];
 		this.identifierPositionStack = new long[20];
 		this.identifierLengthStack = new int[10];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 623cf4b..b2752e4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -14405,7 +14405,8 @@
 		this.options.complianceLevel /*complianceLevel*/,
 		this.options.taskTags/*taskTags*/,
 		this.options.taskPriorities/*taskPriorities*/,
-		this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
+		this.options.isTaskCaseSensitive/*taskCaseSensitive*/,
+		this.options.enablePreviewFeatures /*isPreviewEnabled*/);
 //{ObjectTeams: allow to configure OT/J features  (see also overriding methods):
 	this.scanner.setOTFlags(this.options);
 // SH}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java
index 4d08da2..7f61281 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java
@@ -39,7 +39,8 @@
 				scanner.complianceLevel,
 				scanner.taskTags,
 				scanner.taskPriorities,
-				scanner.isTaskCaseSensitive);
+				scanner.isTaskCaseSensitive,
+				scanner.previewEnabled);
 		setData(data);
 	}
 	
@@ -51,6 +52,7 @@
 			char[][] taskTags,
 			char[][] taskPriorities,
 			boolean isTaskCaseSensitive,
+			boolean isPreviewEnabled,
 			RecoveryScannerData data) {
 		super(false,
 				tokenizeWhiteSpace,
@@ -59,7 +61,8 @@
 				complianceLevel,
 				taskTags,
 				taskPriorities,
-				isTaskCaseSensitive);
+				isTaskCaseSensitive,
+				isPreviewEnabled);
 		setData(data);
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 200a1f7..891ff12 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -61,6 +61,7 @@
 	public boolean useAssertAsAnIndentifier = false;
 	//flag indicating if processed source contains occurrences of keyword assert
 	public boolean containsAssertKeyword = false;
+	public boolean previewEnabled;
 
 	// 1.5 feature
 	public boolean useEnumAsAnIndentifier = false;
@@ -437,7 +438,8 @@
 		long complianceLevel,
 		char[][] taskTags,
 		char[][] taskPriorities,
-		boolean isTaskCaseSensitive) {
+		boolean isTaskCaseSensitive,
+		boolean isPreviewEnabled) {
 
 	this.eofPosition = Integer.MAX_VALUE;
 	this.tokenizeComments = tokenizeComments;
@@ -447,6 +449,7 @@
 	this.consumingEllipsisAnnotations = false;
 	this.complianceLevel = complianceLevel;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
+	this.previewEnabled = isPreviewEnabled;
 	if (taskTags != null) {
 		int taskTagsLength = taskTags.length;
 		int length = taskTagsLength;
@@ -485,6 +488,28 @@
 		long sourceLevel,
 		char[][] taskTags,
 		char[][] taskPriorities,
+		boolean isTaskCaseSensitive,
+		boolean isPreviewEnabled) {
+
+	this(
+		tokenizeComments,
+		tokenizeWhiteSpace,
+		checkNonExternalizedStringLiterals,
+		sourceLevel,
+		sourceLevel,
+		taskTags,
+		taskPriorities,
+		isTaskCaseSensitive,
+		isPreviewEnabled);
+}
+
+public Scanner(
+		boolean tokenizeComments,
+		boolean tokenizeWhiteSpace,
+		boolean checkNonExternalizedStringLiterals,
+		long sourceLevel,
+		char[][] taskTags,
+		char[][] taskPriorities,
 		boolean isTaskCaseSensitive) {
 
 	this(
@@ -495,9 +520,9 @@
 		sourceLevel,
 		taskTags,
 		taskPriorities,
-		isTaskCaseSensitive);
+		isTaskCaseSensitive,
+		false);
 }
-
 public final boolean atEnd() {
 	// This code is not relevant if source is
 	// Only a part of the real stream input
@@ -841,9 +866,7 @@
 			}
 		}
 		return this.currentCharacter;
-	} catch (IndexOutOfBoundsException e) {
-		return -1;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		return -1;
 	}
 }
@@ -911,11 +934,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.unicodeAsBackSlash = false;
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.unicodeAsBackSlash = false;
 		this.currentPosition = temp;
 		return false;
@@ -965,10 +984,7 @@
 				unicodeStore();
 			return result;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return -1;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return -1;
 	}
@@ -1054,10 +1070,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return false;
 	}
@@ -1095,10 +1108,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return false;
 	}
@@ -1239,11 +1249,7 @@
 			    unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = pos;
-		this.withoutUnicodePtr = temp2;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = pos;
 		this.withoutUnicodePtr = temp2;
 		return false;
@@ -2572,9 +2578,7 @@
 			}
 		}
 		//-----------------end switch while try--------------------
-	} catch (IndexOutOfBoundsException e) {
-		// ignore
-	} catch (InvalidInputException e) {
+	} catch (IndexOutOfBoundsException | InvalidInputException e) {
 		// ignore
 	}
 	return;
@@ -5373,8 +5377,9 @@
 // Vanguard Scanner - A Private utility helper class for the scanner.
 private static final class VanguardScanner extends Scanner {
 	
-	public VanguardScanner(long sourceLevel, long complianceLevel) {
-		super (false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, complianceLevel, null/*taskTag*/, null/*taskPriorities*/, false /*taskCaseSensitive*/);
+	public VanguardScanner(long sourceLevel, long complianceLevel, boolean previewEnabled) {
+		super (false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, complianceLevel, null/*taskTag*/,
+				null/*taskPriorities*/, false /*taskCaseSensitive*/, previewEnabled);
 	}
 	
 	@Override
@@ -5580,7 +5585,8 @@
 			this.options.complianceLevel /*complianceLevel*/,
 			this.options.taskTags/*taskTags*/,
 			this.options.taskPriorities/*taskPriorities*/,
-			this.options.isTaskCaseSensitive/*taskCaseSensitive*/)
+			this.options.isTaskCaseSensitive/*taskCaseSensitive*/,
+			this.options.enablePreviewFeatures /*isPreviewEnabled*/)
 		{
 			@Override
 			void updateScanContext(int token) {
@@ -5614,7 +5620,7 @@
 
 private VanguardParser getVanguardParser() {
 	if (this.vanguardParser == null) {
-		this.vanguardScanner = new VanguardScanner(this.sourceLevel, this.complianceLevel);
+		this.vanguardScanner = new VanguardScanner(this.sourceLevel, this.complianceLevel, this.previewEnabled);
 		this.vanguardParser = new VanguardParser(this.vanguardScanner);
 		this.vanguardScanner.setActiveParser(this.vanguardParser);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java
index d20a4d2..d82322a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ScannerHelper.java
@@ -16,7 +16,6 @@
 
 import java.io.BufferedInputStream;
 import java.io.DataInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -165,8 +164,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[START_INDEX][0] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -176,8 +173,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[START_INDEX][1] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -187,8 +182,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[START_INDEX][2] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -198,8 +191,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[PART_INDEX][0] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -209,8 +200,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[PART_INDEX][1] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -220,8 +209,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[PART_INDEX][2] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
@@ -231,8 +218,6 @@
 			readValues[i] = inputStream.readLong();
 		}
 		tempTable[PART_INDEX][3] = readValues;
-	} catch (FileNotFoundException e) {
-		e.printStackTrace();
 	} catch (IOException e) {
 		e.printStackTrace();
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
index 80b30f4..407968b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
@@ -234,9 +234,7 @@
 	    try {
 	        int messageID = Integer.parseInt(key);
 			templates.put(keyFromID(messageID), bundle.getString(key));
-	    } catch(NumberFormatException e) {
-	        // key ill-formed
-		} catch (MissingResourceException e) {
+	    } catch (NumberFormatException | MissingResourceException e) {
 			// available ID
 	    }
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 63a81f0..c9c7678 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -8401,7 +8401,8 @@
 	char[] contents = compilationUnit.getContents();
 	if (contents.length == 0) return start;
 	if (this.positionScanner == null) {
-		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false);
+		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false,
+				this.options.enablePreviewFeatures);
 		this.positionScanner.returnOnlyGreater = true;
 	}
 	this.positionScanner.setSource(contents);
@@ -8440,7 +8441,8 @@
 	char[] contents = compilationUnit.getContents();
 	if (contents.length == 0) return sourceEnd;
 	if (this.positionScanner == null) {
-		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false);
+		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false,
+				this.options.enablePreviewFeatures);
 	}
 	this.positionScanner.setSource(contents);
 	this.positionScanner.resetTo(sourceStart, sourceEnd);
@@ -8469,7 +8471,8 @@
 	char[] contents = compilationUnit.getContents();
 	if (contents.length == 0) return sourceStart;
 	if (this.positionScanner == null) {
-		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false);
+		this.positionScanner = new Scanner(false, false, false, this.options.sourceLevel, this.options.complianceLevel, null, null, false,
+				this.options.enablePreviewFeatures);
 	}
 	this.positionScanner.setSource(contents);
 	this.positionScanner.resetTo(sourceStart, sourceEnd);
@@ -15398,12 +15401,12 @@
 		statement.declarationSourceStart, statement.declarationSourceEnd);
 }
 public void invalidPackageReference(int problem, PackageVisibilityStatement ref) {
-	invalidPackageReference(problem, ref, ProblemSeverities.Error);
-}
-public void invalidPackageReference(int problem, PackageVisibilityStatement ref, int severity) {
-	this.handle(problem, NoArgument, 0, new String[] { CharOperation.charToString(ref.pkgName) }, severity,
-		ref.pkgRef.sourceStart, ref.pkgRef.sourceEnd, this.referenceContext,
-		this.referenceContext == null ? null : this.referenceContext.compilationResult());
+	this.handle(problem,
+			NoArgument,
+			new String[] { CharOperation.charToString(ref.pkgName) },
+			ref.computeSeverity(problem),
+			ref.pkgRef.sourceStart,
+			ref.pkgRef.sourceEnd);
 }
 public void duplicateModuleReference(int problem, ModuleReference ref) {
 	this.handle(problem, 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java
deleted file mode 100644
index ea9f988..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
- *
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.util;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-public final class CompoundNameVector {
-	static int INITIAL_SIZE = 10;
-
-	public int size;
-	int maxSize;
-	char[][][] elements;
-public CompoundNameVector() {
-	this.maxSize = INITIAL_SIZE;
-	this.size = 0;
-	this.elements = new char[this.maxSize][][];
-}
-public void add(char[][] newElement) {
-	if (this.size == this.maxSize)    // knows that size starts <= maxSize
-		System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize *= 2][][]), 0, this.size);
-	this.elements[this.size++] = newElement;
-}
-public void addAll(char[][][] newElements) {
-	if (this.size + newElements.length >= this.maxSize) {
-		this.maxSize = this.size + newElements.length;    // assume no more elements will be added
-		System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize][][]), 0, this.size);
-	}
-	System.arraycopy(newElements, 0, this.elements, this.size, newElements.length);
-	this.size += newElements.length;
-}
-public boolean contains(char[][] element) {
-	for (int i = this.size; --i >= 0;)
-		if (CharOperation.equals(element, this.elements[i]))
-			return true;
-	return false;
-}
-public char[][] elementAt(int index) {
-	return this.elements[index];
-}
-public char[][] remove(char[][] element) {
-	// assumes only one occurrence of the element exists
-	for (int i = this.size; --i >= 0;)
-		if (element == this.elements[i]) {
-			// shift the remaining elements down one spot
-			System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i);
-			this.elements[this.size] = null;
-			return element;
-		}
-	return null;
-}
-public void removeAll() {
-	for (int i = this.size; --i >= 0;)
-		this.elements[i] = null;
-	this.size = 0;
-}
-@Override
-public String toString() {
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0; i < this.size; i++) {
-		buffer.append(CharOperation.toString(this.elements[i])).append("\n"); //$NON-NLS-1$
-	}
-	return buffer.toString();
-}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
index c504b70..abdfce1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 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
@@ -13,13 +13,17 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.util;
 
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 
-public final class HashtableOfPackage {
+public final class HashtableOfPackage<P extends PackageBinding> {
 	// to avoid using Enumerations, walk the individual tables skipping nulls
 	public char[] keyTable[];
-	public PackageBinding valueTable[];
+	private PackageBinding valueTable[];
 
 	public int elementSize; // number of elements in the table
 	int threshold;
@@ -35,6 +39,12 @@
 	this.keyTable = new char[extraRoom][];
 	this.valueTable = new PackageBinding[extraRoom];
 }
+public Iterable<P> values() {
+	return Arrays.stream(this.valueTable)
+			.filter(Objects::nonNull)
+			.map(p -> { @SuppressWarnings("unchecked") P theP = (P)p; return theP; })
+			.collect(Collectors.toList());
+}
 public boolean containsKey(char[] key) {
 	int length = this.keyTable.length,
 		index = CharOperation.hashCode(key) % length;
@@ -49,14 +59,17 @@
 	}
 	return false;
 }
-public PackageBinding get(char[] key) {
+public P get(char[] key) {
 	int length = this.keyTable.length,
 		index = CharOperation.hashCode(key) % length;
 	int keyLength = key.length;
 	char[] currentKey;
 	while ((currentKey = this.keyTable[index]) != null) {
-		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
-			return this.valueTable[index];
+		if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) {
+			@SuppressWarnings("unchecked")
+			P p = (P) this.valueTable[index];
+			return p;
+		}
 		if (++index == length) {
 			index = 0;
 		}
@@ -84,7 +97,7 @@
 	return value;
 }
 private void rehash() {
-	HashtableOfPackage newHashtable = new HashtableOfPackage(this.elementSize * 2); // double the number of expected elements
+	HashtableOfPackage<P> newHashtable = new HashtableOfPackage<P>(this.elementSize * 2); // double the number of expected elements
 	char[] currentKey;
 	for (int i = this.keyTable.length; --i >= 0;)
 		if ((currentKey = this.keyTable[i]) != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
index d243ede..5216b59 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -200,9 +200,7 @@
 	public static byte[] safeReadBytes(Path path) throws IOException {
 		try {
 			return Files.readAllBytes(path);
-		} catch(ClosedByInterruptException e) {
-			return null;
-		} catch (NoSuchFileException e) {
+		} catch (ClosedByInterruptException | NoSuchFileException e) {
 			return null;
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
index 47dffa6..53169bf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
@@ -213,9 +213,7 @@
 					String value = "Missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
 					field.set(null, value);
 				}
-			} catch (IllegalArgumentException e) {
-				// ignore
-			} catch (IllegalAccessException e) {
+			} catch (IllegalArgumentException | IllegalAccessException e) {
 				// ignore
 			}
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java
deleted file mode 100644
index 1d35b12..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
- *
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.util;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-public final class SimpleNameVector {
-
-	static int INITIAL_SIZE = 10;
-
-	public int size;
-	int maxSize;
-	char[][] elements;
-
-	public SimpleNameVector() {
-
-		this.maxSize = INITIAL_SIZE;
-		this.size = 0;
-		this.elements = new char[this.maxSize][];
-	}
-
-	public void add(char[] newElement) {
-
-		if (this.size == this.maxSize) // knows that size starts <= maxSize
-			System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize *= 2][]), 0, this.size);
-		this.elements[this.size++] = newElement;
-	}
-
-	public void addAll(char[][] newElements) {
-
-		if (this.size + newElements.length >= this.maxSize) {
-			this.maxSize = this.size + newElements.length; // assume no more elements will be added
-			System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize][]), 0, this.size);
-		}
-		System.arraycopy(newElements, 0, this.elements, this.size, newElements.length);
-		this.size += newElements.length;
-	}
-
-	public void copyInto(Object[] targetArray){
-
-		System.arraycopy(this.elements, 0, targetArray, 0, this.size);
-	}
-
-	public boolean contains(char[] element) {
-
-		for (int i = this.size; --i >= 0;)
-			if (CharOperation.equals(element, this.elements[i]))
-				return true;
-		return false;
-	}
-
-	public char[] elementAt(int index) {
-		return this.elements[index];
-	}
-
-	public char[] remove(char[] element) {
-
-		// assumes only one occurrence of the element exists
-		for (int i = this.size; --i >= 0;)
-			if (element == this.elements[i]) {
-				// shift the remaining elements down one spot
-				System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i);
-				this.elements[this.size] = null;
-				return element;
-			}
-		return null;
-	}
-
-	public void removeAll() {
-
-		for (int i = this.size; --i >= 0;)
-			this.elements[i] = null;
-		this.size = 0;
-	}
-
-	public int size(){
-
-		return this.size;
-	}
-
-	@Override
-	public String toString() {
-		StringBuffer buffer = new StringBuffer();
-		for (int i = 0; i < this.size; i++) {
-			buffer.append(this.elements[i]).append("\n"); //$NON-NLS-1$
-		}
-		return buffer.toString();
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SortedCharArrays.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SortedCharArrays.java
new file mode 100644
index 0000000..0178dc4
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SortedCharArrays.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Sebastian Zarnekow and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Sebastian Zarnekow - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+import java.util.Comparator;
+
+/**
+ * @since 3.18
+ */
+public class SortedCharArrays {
+
+	// there may be better thresholds available for different scenarios
+	public static final int BINARY_SEARCH_THRESHOLD = 16;
+
+	/**
+	 * @param target same as source array or new array with higher capacity
+	 * @param idx position for new element
+	 * @param currentCount the current number of elements in the source array
+	 * @return given target array
+	 */
+	public static <T> T[] insertIntoArray(T[] src, T[] target, T entry, int idx, int currentCount) {
+		if (src != target) {
+			// src and target point to different instances
+			// -> we need to copy the elements into the new result
+			System.arraycopy(src, 0, target, 0, idx);
+			System.arraycopy(src, idx, target, idx+1, currentCount - idx);
+		} else if (idx != currentCount) {
+			// src and target point to the same instance
+			// -> we need to shift the elements one slot to the right
+			System.arraycopy(src, idx, target, idx+1, currentCount - idx);
+		}
+		target[idx] = entry;
+		return target;
+	}
+
+	/**
+	 * Compares the two char arrays.
+	 * Longer arrays are considered to be smaller than shorter arrays.
+	 * Arrays with the same length are compared char by char lexicographically.
+	 *
+	 * @see Character#compare(char, char)
+	 */
+	public static int compareCharArray(char[] left, char[] right){
+		if (left == right) {
+			return 0;
+		}
+		int l = left.length;
+		int diff = right.length - l;
+		if (diff == 0) {
+			for(int i = 0; i < l && (diff = left[i] - right[i]) == 0; i++) {
+				// all logic is in the loop header
+			}
+		}
+		return diff;
+	}
+	public static final Comparator<char[]> CHAR_ARR_COMPARATOR = SortedCharArrays::compareCharArray;
+
+	/**
+	 * Compares the two char-char arrays.
+	 * Longer arrays are considered to be smaller than shorter arrays.
+	 * Arrays with the same length are compared according to the logic in {@link #compareCharArray(char[], char[])}.
+	 */
+	public static int compareCharCharArray(char[][] left, char[][]right) {
+		if (left == right) {
+			return 0;
+		}
+		int l = left.length;
+		int diff = right.length - l;
+		if (diff == 0) {
+			for(int i = 0; i < l && (diff = compareCharArray(left[i], right[i])) == 0; i++) {
+				// all logic is in the loop header
+			}
+		}
+		return diff;
+	}
+	public static final Comparator<char[][]> CHAR_CHAR_ARR_COMPARATOR = SortedCharArrays::compareCharCharArray;
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
index 4acd3f9..f23cd97 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -93,7 +93,7 @@
  * read-only AST.
  * </p>
  * <p>
- * Clients may create instances of this class using {@link #newAST(int)},
+ * Clients may create instances of this class using {@link #newAST(int, boolean)},
  * but this class is not intended to be subclassed.
  * </p>
  *
@@ -293,9 +293,9 @@
 	 */
 	public static final int JLS12 = 12;
 	/**
-	 * Internal synonym for {@link #JLS11}. Use to alleviate
-	 * deprecation warnings once JLS11 is deprecated
-	 * @since 3.16 
+	 * Internal synonym for {@link #JLS12}. Use to alleviate
+	 * deprecation warnings once JLS12 is deprecated
+	 * @since 3.18 
 	 */
 	static final int JLS12_INTERNAL = JLS12;
 
@@ -363,7 +363,7 @@
 		IProgressMonitor monitor) {
 
 		ASTConverter converter = new ASTConverter(options, isResolved, monitor);
-		AST ast = AST.newAST(level);
+		AST ast = AST.newAST(level, JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 		String sourceModeSetting = (String) options.get(JavaCore.COMPILER_SOURCE);
 		long sourceLevel = CompilerOptions.versionToJdkLevel(sourceModeSetting);
 		if (sourceLevel == 0) {
@@ -378,6 +378,7 @@
 			complianceLevel = sourceLevel;
 		}
 		ast.scanner.complianceLevel = complianceLevel;
+		ast.scanner.previewEnabled = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES));
 		int savedDefaultNodeFlag = ast.getDefaultNodeFlag();
 		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
 		BindingResolver resolver = null;
@@ -403,7 +404,7 @@
 	 * Creates a new Java abstract syntax tree
      * (AST) following the specified set of API rules.
      * <p>
-     * Clients should use this method specifying {@link #JLS11} as the
+     * Clients should use this method specifying {@link #JLS12} as the
      * AST level in all cases, even when dealing with source of earlier JDK versions like 1.3 or 1.4.
      * </p>
      *
@@ -413,10 +414,33 @@
 	 * <ul>
 	 * <li>the API level is not one of the <code>JLS*</code> level constants</li>
 	 * </ul>
+	 * @deprecated Clients should port their code to use the latest JLS* AST API and call
+	 *    {@link #newAST(int, boolean) AST.newAST(AST.JLS12, false)} instead of using this constructor.
      * @since 3.0
 	 */
 	public static AST newAST(int level) {
-		return new AST(level);
+		return new AST(level, false);
+	}
+	
+		/**
+	 * Creates a new Java abstract syntax tree
+     * (AST) following the specified set of API rules.
+     * <p>
+     * Clients should use this method specifying {@link #JLS12} as the
+     * AST level in all cases, even when dealing with source of earlier JDK versions like 1.3 or 1.4.
+     * </p>
+     *
+ 	 * @param level the API level; one of the <code>JLS*</code> level constants
+ 	 * @param previewEnabled <code>true</code> if preview feature is enabled else <code>false</code>
+	 * @return new AST instance following the specified set of API rules.
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the API level is not one of the <code>JLS*</code> level constants</li>
+	 * </ul>
+     * @since 3.19 BETA_JAVA13
+	 */
+	public static AST newAST(int level, boolean previewEnabled) {
+		return new AST(level, previewEnabled);
 	}
 
 	/**
@@ -706,6 +730,7 @@
 	 */
 	int apiLevel;
 
+	private boolean previewEnabled;
 	/**
 	 * Tag bit value. This represents internal state of the tree.
 	 */
@@ -784,7 +809,7 @@
 	 *
 	 * @see JavaCore#getDefaultOptions()
 	 * @deprecated Clients should port their code to use the latest JLS* AST API and call
-	 *    {@link #newAST(int) AST.newAST(AST.JLS9)} instead of using this constructor.
+	 *    {@link #newAST(int, boolean) AST.newAST(AST.JLS12, false)} instead of using this constructor.
 	 */
 	public AST() {
 		this(JavaCore.getDefaultOptions());
@@ -797,7 +822,8 @@
  	 * @param level the API level; one of the <code>JLS*</code> level constants
      * @since 3.0
 	 */
-	private AST(int level) {
+	private AST(int level, boolean previewEnabled) {
+		this.previewEnabled = previewEnabled;
 		switch(level) {
 			case JLS2_INTERNAL :
 			case JLS3_INTERNAL :
@@ -811,7 +837,8 @@
 						ClassFileConstants.JDK1_5 /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;
 			case JLS4_INTERNAL :
 				this.apiLevel = level;
@@ -824,7 +851,8 @@
 						ClassFileConstants.JDK1_7 /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;
 			case JLS8_INTERNAL :
 				this.apiLevel = level;
@@ -837,7 +865,8 @@
 						ClassFileConstants.JDK1_8 /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;	
 			case JLS9_INTERNAL :
 				this.apiLevel = level;
@@ -850,7 +879,8 @@
 						ClassFileConstants.JDK9 /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;	
 			case JLS10_INTERNAL :
 				this.apiLevel = level;
@@ -863,7 +893,8 @@
 						ClassFileConstants.JDK10 /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;	
 			case JLS11_INTERNAL :
 				this.apiLevel = level;
@@ -877,7 +908,8 @@
 						compliance /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						false/*isPreviewEnabled*/);
 				break;
 			case JLS12_INTERNAL :
 				this.apiLevel = level;
@@ -891,7 +923,8 @@
 						compliance /*complianceLevel*/,
 						null/*taskTag*/,
 						null/*taskPriorities*/,
-						true/*taskCaseSensitive*/);
+						true/*taskCaseSensitive*/,
+						previewEnabled);
 				break;
 			default:
 				throw new IllegalArgumentException("Unsupported JLS level"); //$NON-NLS-1$
@@ -921,10 +954,10 @@
 	 *    value type: <code>String</code>)
 	 * @see JavaCore#getDefaultOptions()
 	 * @deprecated Clients should port their code to use the latest JLS* AST API and call
-	 *    {@link #newAST(int) AST.newAST(AST.JLS9)} instead of using this constructor.
+	 *    {@link #newAST(int, boolean) AST.newAST(AST.JLS12, false)} instead of using this constructor.
 	 */
 	public AST(Map options) {
-		this(JLS2);
+		this(JLS2, false);
 		Object sourceLevelOption = options.get(JavaCore.COMPILER_SOURCE);
 		long sourceLevel = ClassFileConstants.JDK1_3;
 		if (JavaCore.VERSION_1_4.equals(sourceLevelOption)) {
@@ -952,7 +985,8 @@
 			complianceLevel /*complianceLevel*/,
 			null/*taskTag*/,
 			null/*taskPriorities*/,
-			true/*taskCaseSensitive*/);
+			true/*taskCaseSensitive*/,
+			JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 	}
 
 	/**
@@ -986,15 +1020,7 @@
 			Constructor c = nodeClass.getDeclaredConstructor(AST_CLASS);
 			Object result = c.newInstance(this.THIS_AST);
 			return (ASTNode) result;
-		} catch (NoSuchMethodException e) {
-			// all AST node classes have a Foo(AST) constructor
-			// therefore nodeClass is not legit
-			throw new IllegalArgumentException(e);
-		} catch (InstantiationException e) {
-			// all concrete AST node classes can be instantiated
-			// therefore nodeClass is not legit
-			throw new IllegalArgumentException(e);
-		} catch (IllegalAccessException e) {
+		} catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
 			// all AST node classes have an accessible Foo(AST) constructor
 			// therefore nodeClass is not legit
 			throw new IllegalArgumentException(e);
@@ -3699,5 +3725,13 @@
 	  	throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
 	  }
 	}
-}
 
+	/**
+	 * 
+	 * @return previewEnabled
+	 * @since 3.19
+	 */
+	public boolean isPreviewEnabled() {
+		return this.previewEnabled;
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index d0e7537..7565afa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -142,7 +142,8 @@
 			sourceLevel /*sourceLevel*/,
 			null /*taskTags*/,
 			null/*taskPriorities*/,
-			true/*taskCaseSensitive*/);
+			true/*taskCaseSensitive*/,
+			JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 		this.monitor = monitor;
 		this.insideComments = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_DOC_COMMENT_SUPPORT));
 //{ObjectTeams: initialize scanner mode from options
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
index fb2b880..d1a1096 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -1366,12 +1366,13 @@
 		converter.compilationUnitSourceLength = this.rawSource.length;
 		converter.scanner.setSource(this.rawSource);
 
-		AST ast = AST.newAST(this.apiLevel);
+		AST ast = AST.newAST(this.apiLevel, JavaCore.ENABLED.equals(this.compilerOptions.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
 		ast.setBindingResolver(new BindingResolver());
 		if ((this.bits & CompilationUnitResolver.STATEMENT_RECOVERY) != 0) {
 			ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
 		}
+		ast.scanner.previewEnabled = JavaCore.ENABLED.equals(this.compilerOptions.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES));
 		converter.setAST(ast);
 		CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil((this.bits & CompilationUnitResolver.IGNORE_METHOD_BODIES) != 0);
 		CompilationUnit compilationUnit = ast.newCompilationUnit();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
index 1e29a5e..1c8312e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BreakStatement.java
@@ -160,7 +160,7 @@
 		result.copyLeadingComment(this);
 		result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
 		if (this.ast.apiLevel >= AST.JLS12_INTERNAL) {
-			result.setExpression((Expression) ASTNode.copySubtree(target, getLabel()));
+			result.setExpression((Expression) ASTNode.copySubtree(target, getExpression()));
 		}
 		return result;
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index 0c78d96..d3c8444 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.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
@@ -304,7 +304,7 @@
 			IProgressMonitor monitor,
 			boolean fromJavaProject) {
 		BindingResolver resolver = null;
-		AST ast = AST.newAST(apiLevel);
+		AST ast = AST.newAST(apiLevel, JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 		String sourceModeSetting = (String) options.get(JavaCore.COMPILER_SOURCE);
 		long sourceLevel = CompilerOptions.versionToJdkLevel(sourceModeSetting);
 		if (sourceLevel == 0) {
@@ -936,7 +936,7 @@
 						CompilationResult compilationResult = unit.compilationResult;
 						org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
 						char[] contents = sourceUnit.getContents();
-						AST ast = AST.newAST(apiLevel);
+						AST ast = AST.newAST(apiLevel, JavaCore.ENABLED.equals(this.options.getMap().get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 						ast.setFlag(flags | AST.RESOLVED_BINDINGS);
 						ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
 						ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
@@ -999,10 +999,7 @@
 			throw e;
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
-		} catch (Error e) {
-			this.handleInternalException(e, unit, null);
-			throw e; // rethrow
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
@@ -1082,7 +1079,7 @@
 						CompilationResult compilationResult = unit.compilationResult;
 						org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
 						char[] contents = sourceUnit.getContents();
-						AST ast = AST.newAST(apiLevel);
+						AST ast = AST.newAST(apiLevel, JavaCore.ENABLED.equals(compilerOptions.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 						ast.setFlag(flags | AST.RESOLVED_BINDINGS);
 						ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
 						ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
@@ -1145,10 +1142,7 @@
 			throw e;
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
-		} catch (Error e) {
-			this.handleInternalException(e, unit, null);
-			throw e; // rethrow
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
@@ -1315,10 +1309,7 @@
 		} catch (AbortCompilation e) {
 			this.handleInternalException(e, unit);
 			return unit == null ? this.unitsToProcess[0] : unit;
-		} catch (Error e) {
-			this.handleInternalException(e, unit, null);
-			throw e; // rethrow
-		} catch (RuntimeException e) {
+		} catch (Error | RuntimeException e) {
 			this.handleInternalException(e, unit, null);
 			throw e; // rethrow
 		} finally {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
index ca374e5..cd266bf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
@@ -462,18 +462,18 @@
 
 	@Override
 	public boolean visit(BreakStatement node) {
-		if (node.getAST().apiLevel() >= JLS12 && node.isImplicit()  && node.getExpression() == null) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled() && node.isImplicit()  && node.getExpression() == null) {
 			return false;
 		}
 		printIndent();
-		if (node.getAST().apiLevel() < JLS12 || (node.getAST().apiLevel() >= JLS12 && !node.isImplicit())) {
+		if (node.getAST().apiLevel() < JLS12 || (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled() && !node.isImplicit())) {
 			this.buffer.append("break"); //$NON-NLS-1$
 		}
 		if (node.getLabel() != null) {
 			this.buffer.append(" ");//$NON-NLS-1$
 			node.getLabel().accept(this);
 		}
-		if (node.getAST().apiLevel() >= JLS12) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled()) {
 			if (node.getExpression() != null) {
 				this.buffer.append(" ");//$NON-NLS-1$
 				node.getExpression().accept(this);
@@ -1520,7 +1520,7 @@
 
 	@Override
 	public boolean visit(SwitchCase node) {
-		if (node.getAST().apiLevel() >= JLS12) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled()) {
 			if (node.isDefault()) {
 				this.buffer.append("default");//$NON-NLS-1$
 				this.buffer.append(node.isSwitchLabeledRule() ? " ->" : ":");//$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index 991b462..1e6c428 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -222,7 +222,8 @@
 							compilerOptions.complianceLevel,
 							null/*taskTags*/,
 							null/*taskPriorities*/,
-							true/*taskCaseSensitive*/);
+							true/*taskCaseSensitive*/,
+							compilerOptions.enablePreviewFeatures/*isPreviewEnabled*/);
 			} else {
 				scanner =
 					new RecoveryScanner(
@@ -233,6 +234,7 @@
 							null/*taskTags*/,
 							null/*taskPriorities*/,
 							true/*taskCaseSensitive*/,
+							compilerOptions.enablePreviewFeatures/*isPreviewEnabled*/,
 							this.recoveryScannerData);
 			}
 			scanner.setSource(this.content);
@@ -2602,7 +2604,7 @@
 		try {
 			int offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNamebreak, node.getStartPosition());
 			rewriteNode(node, BreakStatement.LABEL_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between break and label
-			if (node.getAST().apiLevel() >= JLS12_INTERNAL) {
+			if (node.getAST().apiLevel() >= JLS12_INTERNAL && node.getAST().isPreviewEnabled()) {
 				rewriteNode(node, BreakStatement.EXPRESSION_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between break and label
 			}
 		} catch (CoreException e) {
@@ -3568,7 +3570,7 @@
 		}
 
 		// dont allow switching from case to default or back. New statements should be created.
-		if (node.getAST().apiLevel() >= JLS12_INTERNAL) {
+		if (node.getAST().apiLevel() >= JLS12_INTERNAL && node.getAST().isPreviewEnabled()) {
 			int pos = node.expressions().size() == 0 ? node.getStartPosition() :
 					rewriteNodeList(node, SwitchCase.EXPRESSIONS2_PROPERTY, node.getStartPosition(), Util.EMPTY_STRING, ", "); //$NON-NLS-1$
 			if (isChanged(node, SwitchCase.SWITCH_LABELED_RULE_PROPERTY)) {
@@ -3792,7 +3794,7 @@
 					insertIndent++;
 				}
 				ParagraphListRewriter listRewriter;
-				if (node.getAST().apiLevel() >= JLS12_INTERNAL) {
+				if (node.getAST().apiLevel() >= JLS12_INTERNAL && node.getAST().isPreviewEnabled()) {
 					listRewriter= new SwitchListLabeledRuleRewriter(insertIndent);
 				} else {
 					listRewriter= new SwitchListRewriter(insertIndent);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
index 5f07b07..7e7aa32 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
@@ -396,11 +396,11 @@
 
 	@Override
 	public boolean visit(BreakStatement node) {
-		if (node.getAST().apiLevel() >= JLS12 && node.isImplicit()  && node.getExpression() == null) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled() && node.isImplicit()  && node.getExpression() == null) {
 			return false;
 		}
 		
-		if (node.getAST().apiLevel() < JLS12 || (node.getAST().apiLevel() >= JLS12 && !node.isImplicit())) {
+		if (node.getAST().apiLevel() < JLS12 || (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled() && !node.isImplicit())) {
 			this.result.append("break"); //$NON-NLS-1$
 		}
 		ASTNode label= getChildNode(node, BreakStatement.LABEL_PROPERTY);
@@ -408,7 +408,7 @@
 			this.result.append(' ');
 			label.accept(this);
 		}
-		if (node.getAST().apiLevel() >= JLS12) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled()) {
 			ASTNode expression = getChildNode(node, BreakStatement.EXPRESSION_PROPERTY);
 			if (expression != null ) {
 				this.result.append(' ');
@@ -1032,7 +1032,7 @@
 
 	@Override
 	public boolean visit(SwitchCase node) {
-		if (node.getAST().apiLevel() >= JLS12) {
+		if (node.getAST().apiLevel() >= JLS12 && node.getAST().isPreviewEnabled()) {
 			if (node.isDefault()) {
 				this.result.append("default");//$NON-NLS-1$
 				this.result.append(getBooleanAttribute(node, SwitchCase.SWITCH_LABELED_RULE_PROPERTY) ? " ->" : ":");//$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
index 2812739..3fea04d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -183,9 +184,7 @@
 		node.accept(flattener);
 
 		NodeMarker[] markers= flattener.getMarkers();
-		for (int i= 0; i < markers.length; i++) {
-			resultingMarkers.add(markers[i]); // add to result
-		}
+		Collections.addAll(resultingMarkers, markers);
 
 		String unformatted= flattener.getResult();
 		TextEdit edit= formatNode(node, unformatted, initialIndentationLevel);
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index b34e2e1..9ee17b4 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -100,6 +100,7 @@
 
 	private Object oldCommentFormatOption;
 	private String sourceLevel;
+	public boolean previewEnabled;
 
 	private String sourceString;
 	char[] sourceArray;
@@ -135,6 +136,7 @@
 			this.oldCommentFormatOption = getOldCommentFormatOption(options);
 			String compilerSource = options.get(CompilerOptions.OPTION_Source);
 			this.sourceLevel = compilerSource != null ? compilerSource : CompilerOptions.VERSION_12;
+			this.previewEnabled = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES));
 		} else {
 			Map<String, String> settings = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 			this.originalOptions = new DefaultCodeFormatterOptions(settings);
@@ -403,7 +405,7 @@
 	private void tokenizeSource(int kind) {
 		this.tokens.clear();
 		Scanner scanner = new Scanner(true, false, false/* nls */, CompilerOptions.versionToJdkLevel(this.sourceLevel),
-				null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */);
+				null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */, this.previewEnabled);
 //{ObjectTeams: allow scoped keywords:
 		scanner.parsePureJavaOnly = this.workingOptions.isPureJava;
 		scanner.parseOTJonly = this.isOTJCode;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index 6d4a30f..ae668cd 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -892,9 +892,7 @@
 		if (alignmentForArgumentsInAllocationExpressionOption != null) {
 			try {
 				this.alignment_for_arguments_in_allocation_expression = Integer.parseInt((String) alignmentForArgumentsInAllocationExpressionOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_allocation_expression = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_allocation_expression = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -902,9 +900,7 @@
 		if (alignmentForArgumentsInAnnotationOption != null) {
 			try {
 				this.alignment_for_arguments_in_annotation = Integer.parseInt((String) alignmentForArgumentsInAnnotationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_annotation = Alignment.M_NO_ALIGNMENT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_annotation = Alignment.M_NO_ALIGNMENT;
 			}
 		}
@@ -912,9 +908,7 @@
 		if (alignmentForArgumentsInEnumConstantOption != null) {
 			try {
 				this.alignment_for_arguments_in_enum_constant = Integer.parseInt((String) alignmentForArgumentsInEnumConstantOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_enum_constant = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -922,9 +916,7 @@
 		if (alignmentForArgumentsInExplicitConstructorCallOption != null) {
 			try {
 				this.alignment_for_arguments_in_explicit_constructor_call = Integer.parseInt((String) alignmentForArgumentsInExplicitConstructorCallOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_explicit_constructor_call = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -932,9 +924,7 @@
 		if (alignmentForArgumentsInMethodInvocationOption != null) {
 			try {
 				this.alignment_for_arguments_in_method_invocation = Integer.parseInt((String) alignmentForArgumentsInMethodInvocationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -942,9 +932,7 @@
 		if (alignmentForArgumentsInQualifiedAllocationExpressionOption != null) {
 			try {
 				this.alignment_for_arguments_in_qualified_allocation_expression = Integer.parseInt((String) alignmentForArgumentsInQualifiedAllocationExpressionOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_arguments_in_qualified_allocation_expression = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -952,9 +940,7 @@
 		if (alignmentForAssignmentOption != null) {
 			try {
 				this.alignment_for_assignment = Integer.parseInt((String) alignmentForAssignmentOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_assignment =  Alignment.M_ONE_PER_LINE_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_assignment =  Alignment.M_ONE_PER_LINE_SPLIT;
 			}
 		}
@@ -976,9 +962,7 @@
 		if (alignmentForCompactIfOption != null) {
 			try {
 				this.alignment_for_compact_if = Integer.parseInt((String) alignmentForCompactIfOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_compact_if = Alignment.M_ONE_PER_LINE_SPLIT | Alignment.M_INDENT_BY_ONE;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_compact_if = Alignment.M_ONE_PER_LINE_SPLIT | Alignment.M_INDENT_BY_ONE;
 			}
 		}
@@ -990,9 +974,7 @@
 		if (alignmentForConditionalExpressionOption != null) {
 			try {
 				this.alignment_for_conditional_expression = Integer.parseInt((String) alignmentForConditionalExpressionOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
 			}
 		}
@@ -1002,9 +984,7 @@
 		if (alignmentForEnumConstantsOption != null) {
 			try {
 				this.alignment_for_enum_constants = Integer.parseInt((String) alignmentForEnumConstantsOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_enum_constants = Alignment.M_NO_ALIGNMENT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_enum_constants = Alignment.M_NO_ALIGNMENT;
 			}
 		}
@@ -1012,9 +992,7 @@
 		if (alignmentForExpressionsInArrayInitializerOption != null) {
 			try {
 				this.alignment_for_expressions_in_array_initializer = Integer.parseInt((String) alignmentForExpressionsInArrayInitializerOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1026,9 +1004,7 @@
 		if (alignmentForMethodDeclarationOption != null) {
 			try {
 				this.alignment_for_method_declaration = Integer.parseInt((String) alignmentForMethodDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_method_declaration = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_method_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1040,9 +1016,7 @@
 		if (alignmentForMultipleFieldsOption != null) {
 			try {
 				this.alignment_for_multiple_fields = Integer.parseInt((String) alignmentForMultipleFieldsOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1054,9 +1028,7 @@
 		if (alignmentForParametersInConstructorDeclarationOption != null) {
 			try {
 				this.alignment_for_parameters_in_constructor_declaration = Integer.parseInt((String) alignmentForParametersInConstructorDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
-			} catch (ClassCastException e) {
+			} catch (NumberFormatException | ClassCastException e) {
 				this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1064,9 +1036,7 @@
 		if (alignmentForParametersInMethodDeclarationOption != null) {
 			try {
 				this.alignment_for_parameters_in_method_declaration = Integer.parseInt((String) alignmentForParametersInMethodDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_parameters_in_method_declaration = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_parameters_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1074,9 +1044,7 @@
 		if (alignmentForResourcesInTry != null) {
 			try {
 				this.alignment_for_resources_in_try = Integer.parseInt((String) alignmentForResourcesInTry);
-			} catch (NumberFormatException e) {
-				this.alignment_for_resources_in_try = Alignment.M_NEXT_PER_LINE_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_resources_in_try = Alignment.M_NEXT_PER_LINE_SPLIT;
 			}
 		}
@@ -1084,9 +1052,7 @@
 		if (alignmentForSelectorInMethodInvocationOption != null) {
 			try {
 				this.alignment_for_selector_in_method_invocation = Integer.parseInt((String) alignmentForSelectorInMethodInvocationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_selector_in_method_invocation = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_selector_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1094,9 +1060,7 @@
 		if (alignmentForSuperclassInTypeDeclarationOption != null) {
 			try {
 				this.alignment_for_superclass_in_type_declaration = Integer.parseInt((String) alignmentForSuperclassInTypeDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_superclass_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_superclass_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 			}
 		}
@@ -1104,9 +1068,7 @@
 		if (alignmentForSuperinterfacesInEnumDeclarationOption != null) {
 			try {
 				this.alignment_for_superinterfaces_in_enum_declaration = Integer.parseInt((String) alignmentForSuperinterfacesInEnumDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_superinterfaces_in_enum_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 			}
 		}
@@ -1114,9 +1076,7 @@
 		if (alignmentForSuperinterfacesInTypeDeclarationOption != null) {
 			try {
 				this.alignment_for_superinterfaces_in_type_declaration = Integer.parseInt((String) alignmentForSuperinterfacesInTypeDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_superinterfaces_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_superinterfaces_in_type_declaration = Alignment.M_NEXT_SHIFTED_SPLIT;
 			}
 		}
@@ -1124,9 +1084,7 @@
 		if (alignmentForThrowsClauseInConstructorDeclarationOption != null) {
 			try {
 				this.alignment_for_throws_clause_in_constructor_declaration = Integer.parseInt((String) alignmentForThrowsClauseInConstructorDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_throws_clause_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_throws_clause_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1134,9 +1092,7 @@
 		if (alignmentForThrowsClauseInMethodDeclarationOption != null) {
 			try {
 				this.alignment_for_throws_clause_in_method_declaration = Integer.parseInt((String) alignmentForThrowsClauseInMethodDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.alignment_for_throws_clause_in_method_declaration = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_throws_clause_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1152,9 +1108,7 @@
 		if (alignmentForUnionTypeInMulticatch != null) {
 			try {
 				this.alignment_for_union_type_in_multicatch = Integer.parseInt((String) alignmentForUnionTypeInMulticatch);
-			} catch (NumberFormatException e) {
-				this.alignment_for_union_type_in_multicatch = Alignment.M_COMPACT_SPLIT;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.alignment_for_union_type_in_multicatch = Alignment.M_COMPACT_SPLIT;
 			}
 		}
@@ -1174,9 +1128,7 @@
 		if (alignTypeMembersOnColumnsOption != null) {
 			try {
 				this.align_fields_grouping_blank_lines = Integer.parseInt((String) alignGroupSepartionBlankLinesOption);
-			} catch (NumberFormatException e) {
-				this.align_fields_grouping_blank_lines = Integer.MAX_VALUE;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.align_fields_grouping_blank_lines = Integer.MAX_VALUE;
 			}
 		}
@@ -1326,9 +1278,7 @@
 		if (continuationIndentationOption != null) {
 			try {
 				this.continuation_indentation = Integer.parseInt((String) continuationIndentationOption);
-			} catch (NumberFormatException e) {
-				this.continuation_indentation = 2;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.continuation_indentation = 2;
 			}
 		}
@@ -1336,9 +1286,7 @@
 		if (continuationIndentationForArrayInitializerOption != null) {
 			try {
 				this.continuation_indentation_for_array_initializer = Integer.parseInt((String) continuationIndentationForArrayInitializerOption);
-			} catch (NumberFormatException e) {
-				this.continuation_indentation_for_array_initializer = 2;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.continuation_indentation_for_array_initializer = 2;
 			}
 		}
@@ -1346,9 +1294,7 @@
 		if (blankLinesAfterImportsOption != null) {
 			try {
 				this.blank_lines_after_imports = Integer.parseInt((String) blankLinesAfterImportsOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_after_imports = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_after_imports = 0;
 			}
 		}
@@ -1356,9 +1302,7 @@
 		if (blankLinesAfterPackageOption != null) {
 			try {
 				this.blank_lines_after_package = Integer.parseInt((String) blankLinesAfterPackageOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_after_package = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_after_package = 0;
 			}
 		}
@@ -1366,9 +1310,7 @@
 		if (blankLinesBeforeFieldOption != null) {
 			try {
 				this.blank_lines_before_field = Integer.parseInt((String) blankLinesBeforeFieldOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_field = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_field = 0;
 			}
 		}
@@ -1376,9 +1318,7 @@
 		if (blankLinesBeforeFirstClassBodyDeclarationOption != null) {
 			try {
 				this.blank_lines_before_first_class_body_declaration = Integer.parseInt((String) blankLinesBeforeFirstClassBodyDeclarationOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_first_class_body_declaration = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_first_class_body_declaration = 0;
 			}
 		}
@@ -1386,9 +1326,7 @@
 		if (blankLinesBeforeImportsOption != null) {
 			try {
 				this.blank_lines_before_imports = Integer.parseInt((String) blankLinesBeforeImportsOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_imports = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_imports = 0;
 			}
 		}
@@ -1396,9 +1334,7 @@
 		if (blankLinesBeforeMemberTypeOption != null) {
 			try {
 				this.blank_lines_before_member_type = Integer.parseInt((String) blankLinesBeforeMemberTypeOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_member_type = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_member_type = 0;
 			}
 		}
@@ -1406,9 +1342,7 @@
 		if (blankLinesBeforeMethodOption != null) {
 			try {
 				this.blank_lines_before_method = Integer.parseInt((String) blankLinesBeforeMethodOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_method = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_method = 0;
 			}
 		}
@@ -1416,9 +1350,7 @@
 		if (blankLinesBeforeNewChunkOption != null) {
 			try {
 				this.blank_lines_before_new_chunk = Integer.parseInt((String) blankLinesBeforeNewChunkOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_new_chunk = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_new_chunk = 0;
 			}
 		}
@@ -1426,9 +1358,7 @@
 		if (blankLinesBeforePackageOption != null) {
 			try {
 				this.blank_lines_before_package = Integer.parseInt((String) blankLinesBeforePackageOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_before_package = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_before_package = 0;
 			}
 		}
@@ -1436,9 +1366,7 @@
 		if (blankLinesBetweenImportGroupsOption != null) {
 			try {
 				this.blank_lines_between_import_groups = Integer.parseInt((String) blankLinesBetweenImportGroupsOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_between_import_groups = 1;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_between_import_groups = 1;
 			}
 		}
@@ -1446,9 +1374,7 @@
 		if (blankLinesBetweenTypeDeclarationsOption != null) {
 			try {
 				this.blank_lines_between_type_declarations = Integer.parseInt((String) blankLinesBetweenTypeDeclarationsOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_between_type_declarations = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_between_type_declarations = 0;
 			}
 		}
@@ -1456,9 +1382,7 @@
 		if (blankLinesAtBeginningOfMethodBodyOption != null) {
 			try {
 				this.blank_lines_at_beginning_of_method_body = Integer.parseInt((String) blankLinesAtBeginningOfMethodBodyOption);
-			} catch (NumberFormatException e) {
-				this.blank_lines_at_beginning_of_method_body = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.blank_lines_at_beginning_of_method_body = 0;
 			}
 		}
@@ -1529,9 +1453,7 @@
 		if (commentLineLengthOption != null) {
 			try {
 				this.comment_line_length = Integer.parseInt((String) commentLineLengthOption);
-			} catch (NumberFormatException e) {
-				this.comment_line_length = 80;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.comment_line_length = 80;
 			}
 		}
@@ -1592,9 +1514,7 @@
 			int indentationSize = 4;
 			try {
 				indentationSize = Integer.parseInt((String) indentationSizeOption);
-			} catch (NumberFormatException e) {
-				// keep default
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				// keep default
 			}
 			// reverse values swapping performed by IndentationTabPage
@@ -2384,9 +2304,7 @@
 		if (numberOfEmptyLinesToPreserveOption != null) {
 			try {
 				this.number_of_empty_lines_to_preserve = Integer.parseInt((String) numberOfEmptyLinesToPreserveOption);
-			} catch (NumberFormatException e) {
-				this.number_of_empty_lines_to_preserve = 0;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.number_of_empty_lines_to_preserve = 0;
 			}
 		}
@@ -2407,9 +2325,7 @@
 			int tabSize = 4;
 			try {
 				tabSize = Integer.parseInt((String) tabSizeOption);
-			} catch (NumberFormatException e) {
-				// keep default
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				// keep default
 			}
 			// reverse values swapping performed by IndentationTabPage
@@ -2426,9 +2342,7 @@
 		if (pageWidthOption != null) {
 			try {
 				this.page_width = Integer.parseInt((String) pageWidthOption);
-			} catch (NumberFormatException e) {
-				this.page_width = 120;
-			} catch(ClassCastException e) {
+			} catch(NumberFormatException | ClassCastException e) {
 				this.page_width = 120;
 			}
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
index d21b9bb..4628df1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
@@ -252,7 +252,8 @@
 					complianceLevel,
 					null/*taskTag*/,
 					null/*taskPriorities*/,
-					true /*taskCaseSensitive*/);
+					true /*taskCaseSensitive*/,
+					JavaCore.ENABLED.equals(currentProjectOptions.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 			scanner.setSource(source.toCharArray());
 
 			scanner.resetTo(this.correctionStart, this.correctionEnd);
@@ -305,9 +306,7 @@
 			} finally {
 				JavaCore.setOptions(oldOptions);
 			}
-		} catch (JavaModelException e) {
-			return;
-		} catch (InvalidInputException e) {
+		} catch (JavaModelException | InvalidInputException e) {
 			return;
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index 2530489..62addd9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -602,7 +602,7 @@
  * </p>
  *
  * @param astLevel either {@link #NO_AST} if no AST is wanted,
- * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
+ * or the {@linkplain AST#newAST(int, boolean) AST API level} of the AST if one is wanted
  * @param forceProblemDetection boolean indicating whether problem should be
  *   recomputed even if the source hasn't changed
  * @param owner the owner of working copies that take precedence over the
@@ -671,7 +671,7 @@
  * </p>
  *
  * @param astLevel either {@link #NO_AST} if no AST is wanted,
- * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
+ * or the {@linkplain AST#newAST(int, boolean) AST API level} of the AST if one is wanted
  * @param forceProblemDetection boolean indicating whether problem should be
  *   recomputed even if the source hasn't changed
  * @param enableStatementsRecovery if <code>true</code> statements recovery is enabled.
@@ -750,7 +750,7 @@
  * </p>
  *
  * @param astLevel either {@link #NO_AST} if no AST is wanted,
- * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
+ * or the {@linkplain AST#newAST(int, boolean) AST API level} of the AST if one is wanted
  * @param reconcileFlags the given reconcile flags
  * @param owner the owner of working copies that take precedence over the
  *   original compilation units, or <code>null</code> if the primary working
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 4e8c011..4b09293 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -3868,11 +3868,7 @@
 					verbose_variable_value_after_initialization(variableName, variablePath);
 				manager.variablesWithInitializer.add(variableName);
 				ok = true;
-			} catch (RuntimeException e) {
-				if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE)
-					e.printStackTrace();
-				throw e;
-			} catch (Error e) {
+			} catch (RuntimeException | Error e) {
 				if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE)
 					e.printStackTrace();
 				throw e;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index dfe1061..2b73170 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -312,9 +312,7 @@
 	public static IClassFileReader createDefaultClassFileReader(InputStream stream, int decodingFlag) {
 		try {
 			return new ClassFileReader(Util.getInputStreamAsByteArray(stream, -1), decodingFlag);
-		} catch(ClassFormatException e) {
-			return null;
-		} catch(IOException e) {
+		} catch(ClassFormatException | IOException e) {
 			return null;
 		}
 	}
@@ -336,9 +334,7 @@
 	public static IClassFileReader createDefaultClassFileReader(String fileName, int decodingFlag){
 		try {
 			return new ClassFileReader(Util.getFileByteContent(new File(fileName)), decodingFlag);
-		} catch(ClassFormatException e) {
-			return null;
-		} catch(IOException e) {
+		} catch(ClassFormatException | IOException e) {
 			return null;
 		}
 	}
@@ -374,9 +370,7 @@
 			}
 			byte classFileBytes[] = Util.getZipEntryByteContent(zipEntry, zipFile);
 			return new ClassFileReader(classFileBytes, decodingFlag);
-		} catch(ClassFormatException e) {
-			return null;
-		} catch(IOException e) {
+		} catch(ClassFormatException | IOException e) {
 			return null;
 		} finally {
 			if (zipFile != null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index 277dc1a..346a3fd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -157,11 +157,7 @@
 		}
 		try {
 			info = getJarBinaryTypeInfo();
-		} catch (CoreException e) {
-			// leave info null
-		} catch (IOException e) {
-			// leave info null
-		} catch (ClassFormatException e) {
+		} catch (CoreException | IOException | ClassFormatException e) {
 			// leave info null
 		}
 		manager.putJarTypeInfo(type, info == null ? JavaModelCache.NON_EXISTING_JAR_TYPE_INFO : info);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
index 8be6ab6..1315206 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
@@ -424,11 +424,7 @@
 				final String[] parameterTypes = Signature.getParameterTypes(new String(descriptor));
 				pNames[0] = parameterTypes[0];
 			}
-		} catch (IllegalArgumentException e) {
-			// protect against malformed .class file (e.g. com/sun/crypto/provider/SunJCE_b.class has a 'a' generic signature)
-			signature = methodInfo.getMethodDescriptor();
-			pNames = Signature.getParameterTypes(new String(signature));
-		} catch (JavaModelException e) {
+		} catch (IllegalArgumentException | JavaModelException e) {
 			// protect against malformed .class file (e.g. com/sun/crypto/provider/SunJCE_b.class has a 'a' generic signature)
 			signature = methodInfo.getMethodDescriptor();
 			pNames = Signature.getParameterTypes(new String(signature));
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 284fb64..dc3de37 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -1072,13 +1072,7 @@
 				}
 				return null;
 			}
-		} catch (CoreException e) {
-			// not a zip file
-			if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) {
-				Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
-				e.printStackTrace();
-			}
-		} catch (IOException e) {
+		} catch (CoreException | IOException e) {
 			// not a zip file
 			if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) {
 				Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 8c81b51..90299c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -79,9 +79,7 @@
 		try {
 			UndoEdit undoEdit= edit.apply(document);
 			return undoEdit;
-		} catch (MalformedTreeException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.BAD_TEXT_EDIT_LOCATION);
-		} catch (BadLocationException e) {
+		} catch (MalformedTreeException | BadLocationException e) {
 			throw new JavaModelException(e, IJavaModelStatusConstants.BAD_TEXT_EDIT_LOCATION);
 		}
 	}
@@ -647,20 +645,15 @@
 @Override
 public IType[] getAllTypes() throws JavaModelException {
 	IJavaElement[] types = getTypes();
-	int i;
 	ArrayList allTypes = new ArrayList(types.length);
 	ArrayList typesToTraverse = new ArrayList(types.length);
-	for (i = 0; i < types.length; i++) {
-		typesToTraverse.add(types[i]);
-	}
+	Collections.addAll(typesToTraverse, types);
 	while (!typesToTraverse.isEmpty()) {
 		IType type = (IType) typesToTraverse.get(0);
 		typesToTraverse.remove(type);
 		allTypes.add(type);
 		types = type.getTypes();
-		for (i = 0; i < types.length; i++) {
-			typesToTraverse.add(types[i]);
-		}
+		Collections.addAll(typesToTraverse, types);
 	}
 	IType[] arrayOfAllTypes = new IType[allTypes.size()];
 	allTypes.toArray(arrayOfAllTypes);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
index 5a70128..e2ccdb1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
@@ -432,7 +432,7 @@
 		return getFolders().get(externalFolderPath);
 	}
 
-	private Map<IPath, IFolder> getFolders() {
+	Map<IPath, IFolder> getFolders() {
 		if (this.folders == null) {
 			Map<IPath, IFolder> tempFolders = new LinkedHashMap<>();
 			IProject project = getExternalFoldersProject();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
index bcb3bbe..36b3f1d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
@@ -38,7 +38,8 @@
 				compilerOptions.sourceLevel /*sourceLevel*/,
 				null /*taskTags*/,
 				null/*taskPriorities*/,
-				true/*taskCaseSensitive*/);
+				true/*taskCaseSensitive*/,
+				compilerOptions.enablePreviewFeatures);
 	}
 
 	private static void acceptName(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index d4a003b..69686b7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -660,6 +660,13 @@
 			if (info == null) {
 				info = newElements.get(this);
 			}
+			// Bug 548456: check if some concurrent call already added the info to the manager, do not throw an exception if so
+			if (info == null) {
+				info = manager.getInfo(this);
+				if (info != null) {
+					return info;
+				}
+			}
 			if (info == null) { // a source ref element could not be opened
 				// close the buffer that was opened for the openable parent
 			    // close only the openable's buffer (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62854)
@@ -978,10 +985,7 @@
 					return new String(contents);
 				}
 			}
-		} catch (IllegalArgumentException e) {
-			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=304316
-			return null;
-		} catch (NullPointerException e) {
+		} catch (IllegalArgumentException | NullPointerException e) {
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=304316
 			return null;
 		} catch (SocketTimeoutException e) {
@@ -991,15 +995,7 @@
 		} catch (FileNotFoundException e) {
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=403154
 			validateAndCache(baseLoc, e);
-		} catch (SocketException e) {
-			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=247845 &
-			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=400060
-			throw new JavaModelException(e, IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC);
-		} catch (UnknownHostException e) {
-			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=247845 &
-			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=400060
-			throw new JavaModelException(e, IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC);
-		} catch (ProtocolException e) {
+		} catch (SocketException | UnknownHostException | ProtocolException e) {
 			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=247845 &
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=400060
 			throw new JavaModelException(e, IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC);
@@ -1019,9 +1015,7 @@
 			if (connection2 != null) {
 				try {
 					connection2.getJarFile().close();
-				} catch(IOException e) {
-					// ignore
-				} catch(IllegalStateException e) {
+				} catch(IOException | IllegalStateException e) {
 					/*
 					 * ignore. Can happen in case the stream.close() did close the jar file
 					 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=140750
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 2fcbf6f..9c3baec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -3227,11 +3227,7 @@
 				} else {
 					throw new JavaModelException(e);
 				}
-			} catch (RuntimeException e) {
-				if (JavaModelManager.CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
-					e.printStackTrace();
-				throw e;
-			} catch (Error e) {
+			} catch (RuntimeException | Error e) {
 				if (JavaModelManager.CP_RESOLVE_VERBOSE || CP_RESOLVE_VERBOSE_FAILURE)
 					e.printStackTrace();
 				throw e;
@@ -3626,9 +3622,7 @@
 				try {
 					DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 					cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
-				} catch(SAXException e) {
-					return;
-				} catch(ParserConfigurationException e){
+				} catch(SAXException | ParserConfigurationException e){
 					return;
 				} finally {
 					reader.close();
@@ -4410,16 +4404,7 @@
 			} finally {
 				out.close();
 			}
-		} catch (RuntimeException e) {
-			try {
-				file.delete();
-			} catch(SecurityException se) {
-				// could not delete file: cannot do much more
-			}
-			throw new CoreException(
-				new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
-					Messages.bind(Messages.build_cannotSaveState, info.project.getName()), e));
-		} catch (IOException e) {
+		} catch (RuntimeException | IOException e) {
 			try {
 				file.delete();
 			} catch(SecurityException se) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 23aad55..9c49c54 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -1266,9 +1266,7 @@
 		try {
 			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 			cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
-		} catch (SAXException e) {
-			throw new IOException(Messages.file_badFormat, e);
-		} catch (ParserConfigurationException e) {
+		} catch (SAXException | ParserConfigurationException e) {
 			throw new IOException(Messages.file_badFormat, e);
 		} finally {
 			reader.close();
@@ -1330,9 +1328,7 @@
 				DocumentBuilder parser =
 					DocumentBuilderFactory.newInstance().newDocumentBuilder();
 				node = parser.parse(new InputSource(reader)).getDocumentElement();
-			} catch (SAXException e) {
-				return null;
-			} catch (ParserConfigurationException e) {
+			} catch (SAXException | ParserConfigurationException e) {
 				return null;
 			} finally {
 				reader.close();
@@ -2164,9 +2160,7 @@
 				// cache project options
 				perProjectInfo.options = projectOptions;
 			}
-		} catch (JavaModelException jme) {
-			projectOptions = new Hashtable();
-		} catch (BackingStoreException e) {
+		} catch (JavaModelException | BackingStoreException e) {
 			projectOptions = new Hashtable();
 		}
 //{ObjectTeams: mark non-OT projects:
@@ -2371,9 +2365,7 @@
 			IPackageFragmentRoot root = roots[i];
 			try {
 				IJavaElement[] rootFragments = root.getChildren();
-				for (int j = 0; j < rootFragments.length; j++) {
-					frags.add(rootFragments[j]);
-				}
+				Collections.addAll(frags, rootFragments);
 			} catch (JavaModelException e) {
 				// do nothing
 			}
@@ -2799,8 +2791,7 @@
 				try {
 					in = new BufferedInputStream(new FileInputStream(prefFile));
 					preferences = Platform.getPreferencesService().readPreferences(in);
-				} catch (CoreException e) { // problems loading preference store - quietly ignore
-				} catch (IOException e) { // problems loading preference store - quietly ignore
+				} catch (CoreException | IOException e) { // problems loading preference store - quietly ignore
 				} finally {
 					if (in != null) {
 						try {
@@ -3027,13 +3018,7 @@
 	private IClasspathEntry[][] readFileEntries(Map unkwownElements) {
 		try {
 			return readFileEntriesWithException(unkwownElements);
-		} catch (CoreException e) {
-			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
-			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
-		} catch (IOException e) {
-			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
-			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
-		} catch (ClasspathEntry.AssertionFailedException e) {
+		} catch (CoreException | IOException | ClasspathEntry.AssertionFailedException e) {
 			Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
 			return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index 36d1011..1abf002 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -339,9 +339,7 @@
 			if (docOffset != -1) {
 				return new SourceRange(docOffset + start, docEnd - docOffset);
 			}
-		} catch (InvalidInputException ex) {
-			// try if there is inherited Javadoc
-		} catch (IndexOutOfBoundsException e) {
+		} catch (InvalidInputException | IndexOutOfBoundsException e) {
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=305001
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
index 2b82fc6..529230b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
@@ -14,6 +14,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.Arrays;
+
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IModuleDescription;
 
@@ -61,7 +63,7 @@
 	public IJavaElement[] getChildren() {
 		return this.children;
 	}
-	
+
 	/**
 	 * @see IJavaElement#isStructureKnown()
 	 */
@@ -94,6 +96,32 @@
 	public void setModule(IModuleDescription module) {
 		this.module = module;
 	}
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(getClass().getSimpleName());
+		sb.append(" ["); //$NON-NLS-1$
+		sb.append("isStructureKnown="); //$NON-NLS-1$
+		sb.append(this.isStructureKnown);
+		sb.append(", "); //$NON-NLS-1$
+		if (this.module != null) {
+			sb.append("module="); //$NON-NLS-1$
+			sb.append(this.module);
+			sb.append(", "); //$NON-NLS-1$
+		}
+		if (this.children != null) {
+			sb.append("children="); //$NON-NLS-1$
+			sb.append(Arrays.toString(this.children));
+			sb.append(", "); //$NON-NLS-1$
+		}
+		if (this.nonJavaResources != null) {
+			sb.append("nonJavaResources="); //$NON-NLS-1$
+			sb.append(Arrays.toString(this.nonJavaResources));
+		}
+		sb.append("]"); //$NON-NLS-1$
+		return sb.toString();
+	}
+
 	public IModuleDescription getModule() {
 		return this.module;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
index 5595856..ec2e047 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
@@ -887,20 +887,11 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#getModulesDeclaringPackage(char[][], char[], char[])
+	 * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#getModulesDeclaringPackage(char[][], char[])
 	 */
 	@Override
-	public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
-		String[] pkgName;
-		if (parentPackageName == null)
-			pkgName = new String[] {new String(name)};
-		else {
-			int length = parentPackageName.length;
-			pkgName = new String[length+1];
-			for (int i = 0; i < length; i++)
-				pkgName[i] = new String(parentPackageName[i]);
-			pkgName[length] = new String(name);
-		}
+	public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+		String[] pkgName = Arrays.stream(packageName).map(String::new).toArray(String[]::new);
 		LookupStrategy strategy = LookupStrategy.get(moduleName);
 		switch (strategy) {
 			case Named:
@@ -1145,4 +1136,26 @@
 			return Arrays.copyOf(sourceRoots, count);
 		return sourceRoots;
 	}
+
+	@Override
+	public char[][] listPackages(char[] moduleName) {
+		switch (LookupStrategy.get(moduleName)) {
+			case Named:
+				IPackageFragmentRoot[] packageRoots = findModuleContext(moduleName);
+				Set<String> packages = new HashSet<>();
+				for (IPackageFragmentRoot packageRoot : packageRoots) {
+					try {
+						for (IJavaElement javaElement : packageRoot.getChildren()) {
+							if (javaElement instanceof IPackageFragment && !((IPackageFragment) javaElement).isDefaultPackage())
+								packages.add(javaElement.getElementName());
+						}
+					} catch (JavaModelException e) {
+						Util.log(e, "Failed to retrieve packages from " + packageRoot); //$NON-NLS-1$
+					}
+				}
+				return packages.stream().map(String::toCharArray).toArray(char[][]::new);
+			default:
+				throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
index a85dac4..6666c14 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
@@ -152,9 +152,7 @@
 		try {
 			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 			cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
-		} catch (SAXException e) {
-			throw new IOException(Messages.file_badFormat, e);
-		} catch (ParserConfigurationException e) {
+		} catch (SAXException | ParserConfigurationException e) {
 			throw new IOException(Messages.file_badFormat, e);
 		} finally {
 			reader.close();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
index 301a872..969b6de 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
@@ -83,12 +83,7 @@
 					UserLibrary library;
 					try {
 						library = UserLibrary.createFromString(reader);
-					} catch (IOException e) {
-						Util.log(e, "Exception while initializing user library " + libName); //$NON-NLS-1$
-						instancePreferences.remove(propertyName);
-						preferencesNeedFlush = true;
-						continue;
-					} catch (ClasspathEntry.AssertionFailedException e) {
+					} catch (IOException | ClasspathEntry.AssertionFailedException e) {
 						Util.log(e, "Exception while initializing user library " + libName); //$NON-NLS-1$
 						instancePreferences.remove(propertyName);
 						preferencesNeedFlush = true;
@@ -153,11 +148,9 @@
 				}
 			}
 			JavaCore.setClasspathContainer(containerPath, projects, containers, null);
-		} catch (IOException e) {
-			Util.log(e, "Exception while decoding user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$
 		} catch (JavaModelException e) {
 			Util.log(e, "Exception while setting user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$
-		} catch (ClasspathEntry.AssertionFailedException ase) {
+		} catch (IOException | ClasspathEntry.AssertionFailedException ase) {
 			Util.log(ase, "Exception while decoding user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$
 		}
 		
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 3e01d29..ba43b14 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
@@ -14,10 +14,13 @@
 package org.eclipse.jdt.internal.core.builder;
 
 import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.function.Predicate;
 import java.util.zip.ZipFile;
 
 import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -154,11 +157,7 @@
 	IBinaryType reader = null;
 	try {
 		reader = Util.newClassFileReader(this.binaryFolder.getFile(new Path(qualifiedBinaryFileName)));
-	} catch (CoreException e) {
-		return null;
-	} catch (ClassFormatException e) {
-		return null;
-	} catch (IOException e) {
+	} catch (CoreException | ClassFormatException | IOException e) {
 		return null;
 	}
 	if (reader != null) {
@@ -254,4 +253,21 @@
 	return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false, null);
 }
 
+@Override
+public char[][] listPackages() {
+	Set<String> packageNames = new HashSet<>();
+	IPath basePath = this.binaryFolder.getFullPath();
+	try {
+		this.binaryFolder.accept(r -> {
+			if (r instanceof IFile && SuffixConstants.EXTENSION_class.equals(r.getFileExtension().toLowerCase())) {
+				packageNames.add(r.getParent().getFullPath().makeRelativeTo(basePath).toString().replace('/', '.'));
+			}
+			return true;
+		});
+	} catch (CoreException e) {
+		Util.log(e, "Failed to scan packages of "+this.binaryFolder); //$NON-NLS-1$
+	}
+	return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java
index 5e8aeb7..0d74ebe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java
@@ -101,8 +101,7 @@
 					return new NameEnvironmentAnswer(reader, null, modName);
 				return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), modName);
 			}
-		} catch (IOException e) { // treat as if class file is missing
-		} catch (ClassFormatException e) { // treat as if class file is missing
+		} catch (IOException | ClassFormatException e) { // treat as if class file is missing
 		}
 		return null;
 	}
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 27c8f29..449469a 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
@@ -18,6 +18,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.function.Predicate;
@@ -294,8 +295,7 @@
 					this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), 
 					modName);
 		}
-	} catch (IOException e) { // treat as if class file is missing
-	} catch (ClassFormatException e) { // treat as if class file is missing
+	} catch (IOException | ClassFormatException e) { // treat as if class file is missing
 	}
 	return null;
 }
@@ -323,13 +323,15 @@
 }
 @Override
 public boolean hasCompilationUnit(String pkgName, String moduleName) {
-	for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
-		String fileName = e.nextElement().getName();
-		if (fileName.startsWith(pkgName)
-				&& fileName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)
-				&& fileName.indexOf('/', pkgName.length()+1) == -1)
-			return true;
-	}	
+	if (scanContent()) {
+		for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+			String fileName = e.nextElement().getName();
+			if (fileName.startsWith(pkgName)
+					&& fileName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)
+					&& fileName.indexOf('/', pkgName.length()+1) == -1)
+				return true;
+		}
+	}
 	return false;
 }
 
@@ -399,4 +401,20 @@
 	}
 	return null;
 }
+@Override
+public char[][] listPackages() {
+	if (!scanContent()) // ensure zipFile is initialized
+		return null;
+	char[][] result = new char[this.knownPackageNames.elementSize][];
+	int count = 0;
+	for (int i=0; i<this.knownPackageNames.values.length; i++) {
+		String string = (String) this.knownPackageNames.values[i];
+		if (string != null &&!string.isEmpty()) {
+			result[count++] = string.replace('/', '.').toCharArray();
+		}
+	}
+	if (count < result.length)
+		return Arrays.copyOf(result, count);
+	return result;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
index b9f19e9..197e682 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -215,8 +215,7 @@
 		String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
 		IBinaryType reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName, moduleNameFilter);
 		return createAnswer(fileNameWithoutExtension, reader);
-	} catch (ClassFormatException e) { // treat as if class file is missing
-	} catch (IOException e) { // treat as if class file is missing
+	} catch (ClassFormatException | IOException e) { // treat as if class file is missing
 	}
 	return null;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
index fef78d9..d507ed1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
@@ -325,9 +325,7 @@
 						moduleNameFilter);
 			}
 			return createAnswer(fileNameWithoutExtension, reader);
-		} catch (ClassFormatException e) { 
-			// treat as if class file is missing
-		} catch (IOException e) { 
+		} catch (ClassFormatException | IOException e) { 
 			// treat as if class file is missing
 		}
 		return null;
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 52cd7e0..891aede 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
@@ -25,6 +25,7 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.IModule;
@@ -186,4 +187,7 @@
 		return new char[][] { this.module.name() };
 	return new char[][] { ModuleBinding.UNNAMED };
 }
+public char[][] listPackages() {
+	return CharOperation.NO_CHAR_CHAR;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index 8137e61..9c6865e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -82,12 +82,31 @@
 			IResource[] members = ((IContainer) container).members();
 			dirList = new String[members.length];
 			int index = 0;
-			for (int i = 0, l = members.length; i < l; i++) {
-				IResource m = members[i];
-				String name = m.getName();
-				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
-					// add exclusion pattern check here if we want to hide .class files
-					dirList[index++] = name;
+			if (members.length > 0) {
+				for (int i = 0, l = members.length; i < l; i++) {
+					IResource m = members[i];
+					String name = m.getName();
+					if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
+						// add exclusion pattern check here if we want to hide .class files
+						dirList[index++] = name;
+					}
+				}
+			} else {
+				container = this.sourceFolder.findMember(qualifiedPackageName);
+				if (container instanceof IContainer) {
+					members = ((IContainer) container).members();
+					if (members.length > 0) {
+						dirList = new String[members.length];
+						index = 0;
+						for (int i = 0, l = members.length; i < l; i++) {
+							IResource m = members[i];
+							String name = m.getName();
+							if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
+								// FIXME: check if .java file has any declarations?
+								dirList[index++] = name;
+							}
+						}
+					}
 				}
 			}
 			if (index < dirList.length)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
index 61161cc..f3332ed 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
@@ -121,6 +121,18 @@
 		return false;
 	}
 
+	@Override
+	public char[][] listPackages() {
+		char[][] packages = CharOperation.NO_CHAR_CHAR;
+		if (this.isAutomaticModule) {
+			for (ClasspathLocation cp : this.locations) {
+				packages = CharOperation.arrayConcat(packages, cp.listPackages());
+			}
+			return packages;
+		}
+		return packages;
+	}
+
 	/**
 	 * Combines an IMultiModuleEntry with further locations in order to support patch-module.
 	 * Implemented by adding IMultiModuleEntry functionality to ModulePathEntry.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index ba00f5f..d94b9ac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -561,8 +561,8 @@
 }
 
 @Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
-	String pkgName = new String(CharOperation.concatWith(parentPackageName, name, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+	String pkgName = new String(CharOperation.concatWith(packageName, '/'));
 	String modName = new String(moduleName);
 	LookupStrategy strategy = LookupStrategy.get(moduleName);
 	switch (strategy) {
@@ -685,7 +685,19 @@
 	}
 	return false;
 }
-
+@Override
+public char[][] listPackages(char[] moduleName) {
+	LookupStrategy strategy = LookupStrategy.get(moduleName);
+	switch (strategy) {
+		case Named:
+			IModulePathEntry entry = this.modulePathEntries.get(String.valueOf(moduleName));
+			if (entry == null)
+				return CharOperation.NO_CHAR_CHAR;
+			return entry.listPackages();
+		default:
+			throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+	}
+}
 void setNames(String[] typeNames, SourceFile[] additionalFiles) {
 	// convert the initial typeNames to a set
 	if (typeNames == null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
index 0b47eda..01cf9c8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.util.SortedCharArrays;
 
 public class ReferenceCollection {
 
@@ -58,14 +59,13 @@
 			qualifiedTypeName = internSimpleNames(qualifiedTypeName, false, false);
 			qualifiedTypeName = internedNames.add(qualifiedTypeName);
 			int idx;
-			while ((idx = Arrays.binarySearch(this.qualifiedNameReferences, qualifiedTypeName, CHAR_CHAR_ARR_COMPARATOR)) < 0) {
+			while ((idx = Arrays.binarySearch(this.qualifiedNameReferences, qualifiedTypeName, SortedCharArrays.CHAR_CHAR_ARR_COMPARATOR)) < 0) {
 				this.simpleNameReferences = ensureContainedInSortedOrder(this.simpleNameReferences, qualifiedTypeName[qualifiedTypeName.length - 1]);
 				this.rootReferences = ensureContainedInSortedOrder(this.rootReferences, qualifiedTypeName[0]);
 
 				int length = this.qualifiedNameReferences.length;
 				idx = -(idx+1);
-				char[][][] newArray = new char[length + 1][][];
-				insertIntoArray(this.qualifiedNameReferences, this.qualifiedNameReferences = newArray, qualifiedTypeName, idx);
+				this.qualifiedNameReferences = SortedCharArrays.insertIntoArray(this.qualifiedNameReferences, new char[length + 1][][], qualifiedTypeName, idx, this.qualifiedNameReferences.length);
 
 				qualifiedTypeName = CharOperation.subarray(qualifiedTypeName, 0, qualifiedTypeName.length - 1);
 				char[][][] temp = internQualifiedNames(new char[][][] {qualifiedTypeName}, false);
@@ -78,7 +78,7 @@
 }
 
 public boolean includes(char[] simpleName) {
-	boolean result = sortedArrayContains(this.simpleNameReferences, simpleName, CHAR_ARR_COMPARATOR);
+	boolean result = sortedArrayContains(this.simpleNameReferences, simpleName, SortedCharArrays.CHAR_ARR_COMPARATOR);
 	if (REFERENCE_COLLECTION_DEBUG) {
 		assertIncludes(result, simpleName);
 	}
@@ -86,7 +86,7 @@
 }
 
 public boolean includes(char[][] qualifiedName) {
-	boolean result = sortedArrayContains(this.qualifiedNameReferences, qualifiedName, CHAR_CHAR_ARR_COMPARATOR);
+	boolean result = sortedArrayContains(this.qualifiedNameReferences, qualifiedName, SortedCharArrays.CHAR_CHAR_ARR_COMPARATOR);
 	if (REFERENCE_COLLECTION_DEBUG) {
 		assertIncludes(result, qualifiedName);
 	}
@@ -139,7 +139,7 @@
 }
 
 public boolean insideRoot(char[] rootName) {
-	boolean result = sortedArrayContains(this.rootReferences, rootName, CHAR_ARR_COMPARATOR);
+	boolean result = sortedArrayContains(this.rootReferences, rootName, SortedCharArrays.CHAR_ARR_COMPARATOR);
 	if (REFERENCE_COLLECTION_DEBUG) {
 		if (result != debugIncludes(rootName)) {
 			String message = "Mismatch: " + String.valueOf(rootName) + (result ? " should not " : " should ") + " be included in "  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -152,7 +152,7 @@
 
 private static <T> boolean sortedArrayContains(T[] array, T element, Comparator<? super T> comparator) {
 	int l = array.length;
-	if (l < BINARY_SEARCH_THRESHOLD) {
+	if (l < SortedCharArrays.BINARY_SEARCH_THRESHOLD) {
 		for (int i = 0; i < l; i++)
 			if (element == array[i]) return true;
 		return false;
@@ -161,11 +161,11 @@
 }
 
 private boolean includesSimpleName(char[][] simpleNames) {
-	return intersects(simpleNames, this.simpleNameReferences, CHAR_ARR_COMPARATOR);
+	return intersects(simpleNames, this.simpleNameReferences, SortedCharArrays.CHAR_ARR_COMPARATOR);
 }
 
 private boolean includesQualifiedName(char[][][] qualifiedNames) {
-	if (intersects(qualifiedNames, this.qualifiedNameReferences, CHAR_CHAR_ARR_COMPARATOR)) {
+	if (intersects(qualifiedNames, this.qualifiedNameReferences, SortedCharArrays.CHAR_CHAR_ARR_COMPARATOR)) {
 		return true;
 	}
 	char[][] maybeSimpleName;
@@ -178,11 +178,9 @@
 }
 
 private boolean includesRootName(char[][] rootNames) {
-	return intersects(rootNames, this.rootReferences, CHAR_ARR_COMPARATOR);
+	return intersects(rootNames, this.rootReferences, SortedCharArrays.CHAR_ARR_COMPARATOR);
 }
 
-// TODO there may be better thresholds available for different scenarios
-private static final int BINARY_SEARCH_THRESHOLD = 16;
 private static <T> boolean intersects(T[] firstSortedArr, T[] secondSortedArr, Comparator<? super T> comparator) {
 	/*
 	 * Both arrays are sorted, so we can walk them in pairs.
@@ -205,7 +203,7 @@
 			 * attempt a binary search for the second element to possibly skip a few elements.
 			 */
 			i++;
-			if (l - i > BINARY_SEARCH_THRESHOLD) {
+			if (l - i > SortedCharArrays.BINARY_SEARCH_THRESHOLD) {
 				i = Arrays.binarySearch(firstSortedArr, i, l, secondElement, comparator);
 				if (i >= 0) {
 					return true;
@@ -217,7 +215,7 @@
 			 * the inverse logic is applied here
 			 */
 			j++;
-			if (k - j > BINARY_SEARCH_THRESHOLD) {
+			if (k - j > SortedCharArrays.BINARY_SEARCH_THRESHOLD) {
 				j = Arrays.binarySearch(secondSortedArr, j, k, firstElement, comparator);
 				if (j >= 0) {
 					return true;
@@ -229,19 +227,11 @@
 	return false;
 }
 
-// Generifying this appears to be pointless since arracopy takes an Object array anyways.
-private static void insertIntoArray(Object[] src, Object[] target, Object entry, int idx) {
-	System.arraycopy(src, 0, target, 0, idx);
-	target[idx] = entry;
-	System.arraycopy(src, idx, target, idx+1, src.length - idx);
-}
-
 private static char[][] ensureContainedInSortedOrder(char[][] sortedArray, char[] entry) {
-	int idx = Arrays.binarySearch(sortedArray, entry, CHAR_ARR_COMPARATOR);
+	int idx = Arrays.binarySearch(sortedArray, entry, SortedCharArrays.CHAR_ARR_COMPARATOR);
 	if (idx < 0) {
 		idx = -(idx + 1);
-		char[][] result = new char[sortedArray.length + 1][];
-		insertIntoArray(sortedArray, result, entry, idx);
+		char[][] result = SortedCharArrays.insertIntoArray(sortedArray, new char[sortedArray.length + 1][], entry, idx, sortedArray.length);
 		return result;
 	}
 	return sortedArray;
@@ -367,7 +357,7 @@
 				if (keepWellKnown) {
 					// This code is duplicated to encourage the JIT to inline more stuff
 					if (doSort && isSorted) {
-						if (prev != null && compareCharCharArray(prev, qualifiedName) > 0) {
+						if (prev != null && SortedCharArrays.compareCharCharArray(prev, qualifiedName) > 0) {
 							isSorted = false;
 						}
 						prev = qualifiedName;
@@ -385,7 +375,7 @@
 		qualifiedName = internSimpleNames(qualifiedName, false, false);
 		// This code is duplicated to encourage the JIT to inline more stuff
 		if (doSort && isSorted) {
-			if (prev != null && compareCharCharArray(prev, qualifiedName) > 0) {
+			if (prev != null && SortedCharArrays.compareCharCharArray(prev, qualifiedName) > 0) {
 				isSorted = false;
 			}
 			prev = qualifiedName;
@@ -397,54 +387,12 @@
 		System.arraycopy(keepers, 0, keepers = new char[index][][], 0, index);
 	}
 	if (doSort && !isSorted) {
-		Arrays.sort(keepers, CHAR_CHAR_ARR_COMPARATOR);
+		Arrays.sort(keepers, SortedCharArrays.CHAR_CHAR_ARR_COMPARATOR);
 	}
 	return keepers;
 }
 
 /**
- * Compares the two char arrays.
- * Longer arrays are considered to be smaller than shorter arrays.
- * Arrays with the same length are compared char by char lexicographically.
- *
- * @see Character#compare(char, char)
- */
-private static int compareCharArray(char[] left, char[] right){
-	if (left == right) {
-		return 0;
-	}
-	int l = left.length;
-	int diff = right.length - l;
-	if (diff == 0) {
-		for(int i = 0; i < l && (diff = left[i] - right[i]) == 0; i++) {
-			// all logic is in the loop header
-		}
-	}
-	return diff;
-}
-private static final Comparator<char[]> CHAR_ARR_COMPARATOR = ReferenceCollection::compareCharArray;
-
-/**
- * Compares the two char-char arrays.
- * Longer arrays are considered to be smaller than shorter arrays.
- * Arrays with the same length are compared according to the logic in {@link #compareCharArray(char[], char[])}.
- */
-static int compareCharCharArray(char[][] left, char[][]right) {
-	if (left == right) {
-		return 0;
-	}
-	int l = left.length;
-	int diff = right.length - l;
-	if (diff == 0) {
-		for(int i = 0; i < l && (diff = compareCharArray(left[i], right[i])) == 0; i++) {
-			// all logic is in the loop header
-		}
-	}
-	return diff;
-}
-private static final Comparator<char[][]> CHAR_CHAR_ARR_COMPARATOR = ReferenceCollection::compareCharCharArray;
-
-/**
  * @deprecated
  */
 public static char[][] internSimpleNames(Set<String> simpleStrings) {
@@ -512,7 +460,7 @@
 					keepers[index++] = wellKnownName;
 					// This code is duplicated to encourage the JIT to inline more stuff
 					if (doSort && isSorted) {
-						if (prev != null && compareCharArray(prev, name) > 0) {
+						if (prev != null && SortedCharArrays.compareCharArray(prev, name) > 0) {
 							isSorted = false;
 						}
 						prev = name;
@@ -529,7 +477,7 @@
 		keepers[index++] = internedNames.add(name);
 		// This code is duplicated to encourage the JIT to inline more stuff
 		if (doSort && isSorted) {
-			if (prev != null && compareCharArray(prev, name) > 0) {
+			if (prev != null && SortedCharArrays.compareCharArray(prev, name) > 0) {
 				isSorted = false;
 			}
 			prev = name;
@@ -540,7 +488,7 @@
 		System.arraycopy(keepers, 0, keepers = new char[index][], 0, index);
 	}
 	if (doSort && !isSorted) {
-		Arrays.sort(keepers, CHAR_ARR_COMPARATOR);
+		Arrays.sort(keepers, SortedCharArrays.CHAR_ARR_COMPARATOR);
 	}
 	return keepers;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index bb6d433..8fa6ea9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -307,17 +307,7 @@
 	IBinaryType info = null;
 	try {
 		info = Util.newClassFileReader(file);
-	} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
-		if (TypeHierarchy.DEBUG) {
-			e.printStackTrace();
-		}
-		return null;
-	} catch (java.io.IOException e) {
-		if (TypeHierarchy.DEBUG) {
-			e.printStackTrace();
-		}
-		return null;
-	} catch (CoreException e) {
+	} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException | java.io.IOException | CoreException e) {
 		if (TypeHierarchy.DEBUG) {
 			e.printStackTrace();
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
index 8d5a4c6..722ce5b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2017 IBM Corporation and others.
+ * Copyright (c) 2005, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -45,8 +45,8 @@
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -500,7 +500,7 @@
 	@Override
 	public void consumePackage(char[] pkgName) {
 		this.compoundName = CharOperation.splitOn('/', pkgName);
-		this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
+		this.compilerBinding = new PlainPackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
index 221a9d9..01d8f78 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
@@ -275,7 +275,8 @@
 				this.options.sourceLevel /*sourceLevel*/,
 				this.options.taskTags/*taskTags*/,
 				this.options.taskPriorities/*taskPriorities*/,
-				this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
+				this.options.isTaskCaseSensitive/*taskCaseSensitive*/,
+				this.options.enablePreviewFeatures /*isPreviewEnabled*/);
 //{ObjectTeams: allow to configure OT/J features.
 	    this.scanner.setOTFlags(this.options);
 // SH}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java
index f7c9e6a..cba6c05 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java
@@ -140,9 +140,7 @@
 		toCompile.toArray(sources);
 		compiler.compile(sources);
 		String[] mods = environment.getModules();
-		for (String string : mods) {
-			required.add(string);
-		}
+		Collections.addAll(required, mods);
 		Collections.sort(required, new Comparator<String>() {
 			@Override
 			public int compare(String o1, String o2) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index 958062a..772150b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -713,9 +713,7 @@
 			}
 		}
 		return this.currentCharacter;
-	} catch (IndexOutOfBoundsException e) {
-		return -1;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		return -1;
 	}
 }
@@ -783,11 +781,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.unicodeAsBackSlash = false;
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.unicodeAsBackSlash = false;
 		this.currentPosition = temp;
 		return false;
@@ -837,10 +831,7 @@
 				unicodeStore();
 			return result;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return -1;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return -1;
 	}
@@ -926,10 +917,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return false;
 	}
@@ -967,10 +955,7 @@
 				unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = temp;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = temp;
 		return false;
 	}
@@ -1111,11 +1096,7 @@
 			    unicodeStore();
 			return true;
 		}
-	} catch (IndexOutOfBoundsException e) {
-		this.currentPosition = pos;
-		this.withoutUnicodePtr = temp2;
-		return false;
-	} catch(InvalidInputException e) {
+	} catch(IndexOutOfBoundsException | InvalidInputException e) {
 		this.currentPosition = pos;
 		this.withoutUnicodePtr = temp2;
 		return false;
@@ -2379,9 +2360,7 @@
 			}
 		}
 		//-----------------end switch while try--------------------
-	} catch (IndexOutOfBoundsException e) {
-		// ignore
-	} catch (InvalidInputException e) {
+	} catch (IndexOutOfBoundsException | InvalidInputException e) {
 		// ignore
 	}
 	return;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
index 6858eeb..52401cb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -443,9 +443,7 @@
 		try {
 			edit.apply(document, TextEdit.NONE);
 			return document.get();
-		} catch (MalformedTreeException e) {
-			e.printStackTrace();
-		} catch (BadLocationException e) {
+		} catch (MalformedTreeException | BadLocationException e) {
 			e.printStackTrace();
 		}
 		return original;
@@ -904,11 +902,7 @@
 			if (reader != null) {
 				return reader.getVersion();
 			}
-		} catch (CoreException e) {
-			// ignore
-		} catch(ClassFormatException e) {
-			// ignore
-		} catch(IOException e) {
+		} catch(CoreException | ClassFormatException | IOException e) {
 			// ignore
 		}
 		return 0;
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index 01ba337..2fe996a 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2018 Eclipse Foundation and others.
+  Copyright (c) 2012, 2019 Eclipse Foundation and others.
   All rights reserved. This program and the accompanying materials
   are made available under the terms of the Eclipse Distribution License v1.0
   which accompanies this distribution, and is available at
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.core</artifactId>
     <groupId>eclipse.jdt.core</groupId>
-    <version>4.12.0-SNAPSHOT</version>
+    <version>4.13.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.core</artifactId>
-  <version>3.18.0-SNAPSHOT</version>
+  <version>3.19.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
index 22c7a2a..bff5cfe 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
@@ -845,14 +845,7 @@
 			}
 			// record all references found inside the .class file
 			extractReferenceFromConstantPool(contents, reader);
-		} catch (ClassFormatException e) {
-			// ignore
-			this.document.removeAllIndexEntries();
-			Util.log(new Status(IStatus.WARNING,
-					JavaCore.PLUGIN_ID,
-					"The Java indexing could not index " + this.document.getPath() + ". This .class file doesn't follow the class file format specification. Please report this issue against the .class file vendor", //$NON-NLS-1$ //$NON-NLS-2$
-					e));
-		} catch (RuntimeException e) {
+		} catch (ClassFormatException | RuntimeException e) {
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=182154
 			// logging the entry that could not be indexed and continue with the next one
 			// we remove all entries relative to the boggus document
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
index e952625..ffa90a9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
@@ -228,14 +228,7 @@
 
 			// request to save index when all cus have been indexed... also sets state to SAVED_STATE
 			this.manager.request(new SaveIndex(this.containerPath, this.manager));
-		} catch (CoreException e) {
-			if (JobManager.VERBOSE) {
-				Util.verbose("-> failed to index " + this.project + " because of the following exception:", System.err); //$NON-NLS-1$ //$NON-NLS-2$
-				e.printStackTrace();
-			}
-			this.manager.removeIndex(this.containerPath);
-			return false;
-		} catch (IOException e) {
+		} catch (CoreException | IOException e) {
 			if (JobManager.VERBOSE) {
 				Util.verbose("-> failed to index " + this.project + " because of the following exception:", System.err); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
index 32e1ca0..88b80cd 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
@@ -135,14 +135,7 @@
 
 			// request to save index when all class files have been indexed... also sets state to SAVED_STATE
 			this.manager.request(new SaveIndex(this.containerPath, this.manager));
-		} catch (CoreException e) {
-			if (JobManager.VERBOSE) {
-				Util.verbose("-> failed to index " + this.folder + " because of the following exception:", System.err); //$NON-NLS-1$ //$NON-NLS-2$
-				e.printStackTrace();
-			}
-			this.manager.removeIndex(this.containerPath);
-			return false;
-		} catch (IOException e) {
+		} catch (CoreException | IOException e) {
 			if (JobManager.VERBOSE) {
 				Util.verbose("-> failed to index " + this.folder + " because of the following exception:", System.err); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index db613ca..083fbc0 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -328,8 +328,8 @@
 }
 
 @Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) {
-	String qualifiedPackageName = String.valueOf(CharOperation.concatWith(parentPackageName, packageName, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+	String qualifiedPackageName = String.valueOf(CharOperation.concatWith(packageName, '/'));
 	LookupStrategy strategy = LookupStrategy.get(moduleName);
 	if (strategy == LookupStrategy.Named) {
 		if (this.moduleToClassPathLocations != null) {
@@ -359,6 +359,22 @@
 }
 
 @Override
+public char[][] listPackages(char[] moduleName) { LookupStrategy strategy = LookupStrategy.get(moduleName);
+	switch (strategy) {
+		case Named:
+			if (this.moduleLocations != null) {
+				ClasspathLocation location = this.moduleLocations.get(String.valueOf(moduleName));
+				if (location == null)
+					return CharOperation.NO_CHAR_CHAR;
+				return location.listPackages();
+			}
+			return CharOperation.NO_CHAR_CHAR;
+		default:
+			throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+	}
+}
+
+@Override
 public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) {
 	String qualifiedPackageNameString = String.valueOf(CharOperation.concatWith(qualifiedPackageName, '/'));
 	LookupStrategy strategy = LookupStrategy.get(moduleName);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index f9b90ea..3269223 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -1453,11 +1453,7 @@
 		this.matchesToProcess[i] = null; // release reference to processed possible match
 		try {
 			process(possibleMatch, bindingsWereCreated);
-		} catch (AbortCompilation e) {
-			// problem with class path: it could not find base classes
-			// continue and try next matching openable reporting inaccurate matches (since bindings will be null)
-			bindingsWereCreated = false;
-		} catch (JavaModelException e) {
+		} catch (AbortCompilation | JavaModelException e) {
 			// problem with class path: it could not find base classes
 			// continue and try next matching openable reporting inaccurate matches (since bindings will be null)
 			bindingsWereCreated = false;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
index c512ee1..9990d6a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
@@ -236,9 +236,7 @@
 				if (matches(binding))
 					collectSuperTypeNames(binding, binding.compoundName);
 			}
-		} catch (AbortCompilation e) {
-			// ignore: continue with next element
-		} catch (JavaModelException e) {
+		} catch (AbortCompilation | JavaModelException e) {
 			// ignore: continue with next element
 		}
 	}