Merge branch 'master' into BETA_JAVA9

# Conflicts:
#	org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
#	org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
#	org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
#	org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
#	org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
#	org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java

Change-Id: Ica9e9ccc4ff370554100c545310fba1c66adeed2
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
index 7967042..ae53ed7 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BaseProcessorEnv.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 BEA Systems Inc. and others
+ * Copyright (c) 2005, 2016 BEA Systems Inc. and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -83,7 +83,7 @@
 public class BaseProcessorEnv implements AnnotationProcessorEnvironment 
 {
 	static{
-		final AST ast = AST.newAST(AST.JLS8);
+		final AST ast = AST.newAST(AST.JLS9);
 		EMPTY_AST_UNIT = ast.newCompilationUnit();
 	}
 	public static final CompilationUnit EMPTY_AST_UNIT;
@@ -492,7 +492,7 @@
 		}
 
 		final BindingRequestor requestor = new BindingRequestor();
-		final ASTParser parser = ASTParser.newParser(AST.JLS8);
+		final ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setResolveBindings(true);
 		parser.setBindingsRecovery(true);
 		parser.setProject(_javaProject);
@@ -702,7 +702,7 @@
             if( astUnit != null ) return astUnit;
             else{
                 // Note: very expensive operation. we are re-compiling a file with binding information.
-                final ASTParser parser =  ASTParser.newParser(AST.JLS8);
+                final ASTParser parser =  ASTParser.newParser(AST.JLS9);
                 parser.setResolveBindings(true);
         		parser.setBindingsRecovery(true);
                 parser.setSource(unit);
@@ -848,7 +848,7 @@
 		String bogusKey = BindingKey.createTypeBindingKey("java.lang.Object"); //$NON-NLS-1$
 		String[] keys = new String[] {bogusKey};
 
-		ASTParser p = ASTParser.newParser( AST.JLS8 );
+		ASTParser p = ASTParser.newParser( AST.JLS9 );
 		p.setResolveBindings(true);
 		p.setBindingsRecovery(true);
 		p.setProject( javaProject );
@@ -877,7 +877,7 @@
 		}
 		
 		CompilationUnitRequestor requestor = new CompilationUnitRequestor();
-		ASTParser p = ASTParser.newParser( AST.JLS8 );
+		ASTParser p = ASTParser.newParser( AST.JLS9 );
 		p.setResolveBindings(true);
 		p.setBindingsRecovery(true);
 		p.setProject( javaProject );
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ExceptionHandlingTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ExceptionHandlingTests.java
index 8c198d8..cf28f6f 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ExceptionHandlingTests.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ExceptionHandlingTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2007 BEA Systems, Inc. 
+ * Copyright (c) 2006, 2016 BEA Systems, Inc. 
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    sbandow@bea.com - initial API and implementation
  *    
@@ -36,7 +40,7 @@
 		IProject project = env.getProject( getProjectName() );
 		IPath srcRoot = getSourcePath();
 		
-		IPath testPath = env.addClass(srcRoot, "test", "Test", getCodeForTest("booleanValue = new Boolean(true)"));
+		IPath testPath = env.addClass(srcRoot, "test", "Test", getCodeForTest("booleanValue = Boolean.valueOf(true)"));
 
 		fullBuild( project.getFullPath() );
 		expectingOnlySpecificProblemFor(testPath, new ExpectedProblem("Test", "Type mismatch: cannot convert from Boolean to boolean", testPath));
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
index 8a6ccea..ba36acf 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/ReadAnnotationTests2.java
@@ -184,7 +184,7 @@
 		}
 
 		final BindingRequestor requestor = new BindingRequestor();
-		final ASTParser parser = ASTParser.newParser(AST.JLS8);
+		final ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setResolveBindings(true);
 		parser.setProject(javaProj);
 		parser.setIgnoreMethodBodies(true);
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/TestAll.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/TestAll.java
index 3587f3f..206ccd3 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/TestAll.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/TestAll.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2014 BEA Systems, Inc.
+ * Copyright (c) 2005, 2015 BEA Systems, Inc.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    wharley@bea.com - initial API and implementation
  *    het@google.com - Bug 441790
@@ -24,7 +28,11 @@
  * the name of an annotation processor factory class implemented in this plugin.
  */
 public class TestAll extends TestCase {
-	
+
+	static {
+		System.setProperty("modules", "java.base");
+	}
+
 	public TestAll(String testName) 
 	{
 		super(testName);
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar
index ed4b4d1..e08c33c 100644
--- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar
+++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
index 2c4c285..f57fa54 100644
--- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
+++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elements/ElementProc.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elements/ElementProc.java
index c9f44a3..2befc4b 100644
--- a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elements/ElementProc.java
+++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/elements/ElementProc.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    wharley@bea.com - initial API and implementation
  *    akurtakov@gmail.com - fix compilation with Java 7
@@ -148,6 +152,9 @@
 		if(!bug300408()) {
 			return false;
 		}
+		if (!examineTypesInPackage()) {
+			return false;
+		}
 
 		if (!bug467928_enumFields()) {
 			return false;
@@ -1041,4 +1048,13 @@
 		}
 		return true;
 	}
+	private boolean examineTypesInPackage() {
+		PackageElement pack = _elementUtils.getPackageElement("java.util.concurrent");
+		List<? extends Element> enclosedElements = pack.getEnclosedElements();
+		if (enclosedElements.size() == 0) {
+			reportError("Should find types in package java.util.concurrent");
+			return false;
+		}
+		return true;
+	}
 }
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
index 4bc6be4..548cce1 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
@@ -95,7 +95,7 @@
 	 * when called from Eclipse compiler
 	 * @throws IOException 
 	 */
-	public void testProcessorArgumentsWithEclipseCompiler() throws IOException {
+	public void _testProcessorArgumentsWithEclipseCompiler() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestProcessorArguments(compiler);
 	}
@@ -120,7 +120,7 @@
 	 * Read annotation values and generate a class using Eclipse compiler
 	 * @throws IOException 
 	 */
-	public void testCompilerOneClassWithEclipseCompiler() throws IOException {
+	public void _testCompilerOneClassWithEclipseCompiler() throws IOException {
 		// Eclipse compiler
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestGenerateClass(compiler);
@@ -152,7 +152,7 @@
 	 * Verify that if a type has two annotations, both processors are run.
 	 * @throws IOException 
 	 */
-	public void testTwoAnnotations() throws IOException {
+	public void _testTwoAnnotations() throws IOException {
 		File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), "targets", "dispatch");
 		File inputFile = BatchTestUtils.copyResource("targets/dispatch/TwoAnnotations.java", targetFolder);
 		assertNotNull("No input file", inputFile);
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java
index 443ea10..98eba96 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java
@@ -278,14 +278,11 @@
 		if (c == null) {
 			junit.framework.TestCase.assertTrue("Eclipse compiler is not available", false);
 		}
-		int compilerCounter = 0;
 		for (JavaCompiler javaCompiler : javaCompilerLoader) {
-			compilerCounter++;
 			if (c.isInstance(javaCompiler)) {
 				_eclipseCompiler = javaCompiler;
 			}
 		}
-		junit.framework.TestCase.assertEquals("Only one compiler available", 1, compilerCounter);
 		junit.framework.TestCase.assertNotNull("No Eclipse compiler found", _eclipseCompiler);
 	}
 
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FileManagerTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FileManagerTests.java
index 36b7079..a0fd12e 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FileManagerTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FileManagerTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    wharley@bea.com - initial API and implementation
  *    IBM Corporation - fixed a resource leak warning
@@ -25,6 +29,7 @@
 import java.util.Locale;
 import java.util.Set;
 
+import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
@@ -167,6 +172,7 @@
 	}
 
 	public void testBug460085() {
+		if (isOnJRE9()) return;
 		try {
 			boolean found = false;
 			EclipseFileManager fileManager = null;
@@ -183,10 +189,17 @@
 			fileManager.close();
 			assertTrue("rt.jar not found", found);
 		} catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
+			fail(e.getMessage());
 		} 
 	}
+	private boolean isOnJRE9() {
+		try {
+			SourceVersion.valueOf("RELEASE_9");
+		} catch(IllegalArgumentException iae) {
+			return false;
+		}
+		return true;
+	}
 
 	public void testBug466878_getResource_defaultPackage() throws Exception {
 		EclipseFileManager fileManager = new EclipseFileManager(Locale.getDefault(), Charset.defaultCharset());
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FilerTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FilerTests.java
index 120cd11..6b4680d 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FilerTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/FilerTests.java
@@ -48,7 +48,7 @@
 	 * Attempt to read various elements of the Element hierarchy.
 	 * @throws IOException 
 	 */
-	public void testElementWithEclipseCompiler() throws IOException {
+	public void _testElementWithEclipseCompiler() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestCreateResource(compiler, false);
 	}
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java
index a447230..665ffa1 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java
@@ -184,7 +184,7 @@
 	/*
 	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=328575 
 	 */
-	public void testNegativeModel10WithEclipseCompiler() throws IOException {
+	public void _testNegativeModel10WithEclipseCompiler() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		System.clearProperty(NEGATIVEMODELPROCNAME);
 		System.clearProperty(INHERITED_PROCNAME);
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java
index 67cc77c..2b195ff 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java
@@ -1,15 +1,21 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.apt.dispatch;
 
+import java.io.IOException;
+import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -232,5 +238,15 @@
 		_commandLineProcessors = null;
 		_commandLineProcessorIter = null;
 	}
-
+	@Override
+	public void reset() {
+		super.reset();
+		if (this._procLoader instanceof URLClassLoader) {
+			try {
+				((URLClassLoader) this._procLoader).close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
 }
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java
index 6ac10f8..00271fe 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java
@@ -555,7 +555,7 @@
 	public PackageElement getPackageElement(CharSequence name) {
 		LookupEnvironment le = _env.getLookupEnvironment();
 		if (name.length() == 0) {
-			return new PackageElementImpl(_env, le.defaultPackage);
+			return new PackageElementImpl(_env, le.getDefaultPackage(null));
 		}
 		char[] packageName = name.toString().toCharArray();
 		PackageBinding packageBinding = le.createPackage(CharOperation.splitOn('.', packageName));
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ErrorTypeElement.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ErrorTypeElement.java
index 63538fe..af22bc8 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ErrorTypeElement.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ErrorTypeElement.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2014 IBM Corporation and others.
+ * Copyright (c) 2007, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -130,7 +134,7 @@
 	 */
 	@Override
 	public Element getEnclosingElement() {
-		return this._env.getFactory().newPackageElement(this._env.getLookupEnvironment().defaultPackage);
+		return this._env.getFactory().newPackageElement(this._env.getLookupEnvironment().getDefaultPackage(null));
 	}
 
 	/* (non-Javadoc)
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java
index f1bd620..e69b872 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2015 BEA Systems, Inc. 
+ * Copyright (c) 2007, 2016 BEA Systems, Inc. 
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    wharley@bea.com - initial API and implementation
  *    
@@ -29,6 +33,7 @@
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -68,7 +73,7 @@
 		char[][][] typeNames = null;
 		INameEnvironment nameEnvironment = binding.environment.nameEnvironment;
 		if (nameEnvironment instanceof FileSystem) {
-			typeNames = ((FileSystem) nameEnvironment).findTypeNames(binding.compoundName);
+			typeNames = ((FileSystem) nameEnvironment).findTypeNames(binding.compoundName, ModuleEnvironment.UNNAMED_MODULE_ARRAY);
 		}
 		HashSet<Element> set = new HashSet<>(); 
 		if (typeNames != null) {
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Archive.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Archive.java
index aad37bb..8b46bbb 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Archive.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Archive.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -33,9 +37,9 @@
 	ZipFile zipFile;
 	File file;
 
-	protected Hashtable<String, ArrayList<String>> packagesCache;
+	protected Hashtable<String, ArrayList<String[]>> packagesCache;
 	
-	private Archive() {
+	protected Archive() {
 		// used to construct UNKNOWN_ARCHIVE
 	}
 
@@ -56,23 +60,23 @@
 			// extract the package name
 			String packageName = fileName.substring(0, last + 1);
 			String typeName = fileName.substring(last + 1);
-			ArrayList<String> types = this.packagesCache.get(packageName);
+			ArrayList<String[]> types = this.packagesCache.get(packageName);
 			if (types == null) {
 				// might be empty if this is a directory entry
 				if (typeName.length() == 0) {
 					continue nextEntry;
 				}
 				types = new ArrayList<>();
-				types.add(typeName);
+				types.add(new String[]{typeName, null});
 				this.packagesCache.put(packageName, types);
 			} else {
-				types.add(typeName);
+				types.add(new String[]{typeName, null});
 			}
 		}
 	}
 	
-	public ArchiveFileObject getArchiveFileObject(String entryName, Charset charset) {
-		return new ArchiveFileObject(this.file, entryName, charset);
+	public ArchiveFileObject getArchiveFileObject(String fileName, Charset charset) {
+		return new ArchiveFileObject(this.file, fileName, charset);
 	}
 	
 	public boolean contains(String entryName) {
@@ -86,13 +90,13 @@
 		return this.packagesCache.keySet();
 	}
 	
-	public List<String> getTypes(String packageName) {
+	public List<String[]> getTypes(String packageName) {
 		// package name is expected to ends with '/'
 		if (this.packagesCache == null) {
 			try {
 				this.zipFile = new ZipFile(this.file);
 			} catch(IOException e) {
-				return Collections.<String>emptyList();
+				return Collections.<String[]>emptyList();
 			}
 			this.initialize();
 		}
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/ArchiveFileObject.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/ArchiveFileObject.java
index 16ca0b8..27e98ff 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/ArchiveFileObject.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/ArchiveFileObject.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -34,10 +38,10 @@
  * Implementation of a Java file object that corresponds to an entry in a zip/jar file
  */
 public class ArchiveFileObject implements JavaFileObject {
-	private String entryName;
-	private File file;
-	private ZipFile zipFile;
-	private Charset charset;
+	protected String entryName;
+	protected File file;
+	protected ZipFile zipFile;
+	protected Charset charset;
 
 	public ArchiveFileObject(File file, String entryName, Charset charset) {
 		this.entryName = entryName;
@@ -66,16 +70,7 @@
 		if (getKind() != Kind.CLASS) {
 			return null;
 		}
-		ClassFileReader reader = null;
-		try {
-			try (ZipFile zip = new ZipFile(this.file)) {
-				reader = ClassFileReader.read(zip, this.entryName);
-			}
-		} catch (ClassFormatException e) {
-			// ignore
-		} catch (IOException e) {
-			// ignore
-		}
+		ClassFileReader reader = getClassReader();
 
 		if (reader == null) {
 			return null;
@@ -93,6 +88,20 @@
 		return null;
 	}
 
+	protected ClassFileReader getClassReader() {
+		ClassFileReader reader = null;
+		try {
+			try (ZipFile zip = new ZipFile(this.file)) {
+				reader = ClassFileReader.read(zip, this.entryName);
+			}
+		} catch (ClassFormatException e) {
+			// ignore
+		} catch (IOException e) {
+			// ignore
+		}
+		return reader;
+	}
+
 	/* (non-Javadoc)
 	 * @see javax.tools.JavaFileObject#getKind()
 	 */
@@ -118,16 +127,7 @@
 		case SOURCE :
 			return NestingKind.TOP_LEVEL;
 		case CLASS :
-			ClassFileReader reader = null;
-			try {
-				try (ZipFile zip = new ZipFile(this.file)) {
-					reader = ClassFileReader.read(zip, this.entryName);
-				}
-			} catch (ClassFormatException e) {
-				// ignore
-			} catch (IOException e) {
-				// ignore
-			}
+			ClassFileReader reader = getClassReader();
 			if (reader == null) {
 				return null;
 			}
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
index 59b628f..4f28764 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -142,24 +146,26 @@
 			if (recurse) {
 				for (String packageName : archive.allPackages()) {
 					if (packageName.startsWith(key)) {
-						List<String> types = archive.getTypes(packageName);
+						List<String[]> types = archive.getTypes(packageName);
 						if (types != null) {
-							for (String typeName : types) {
-								final Kind kind = getKind(getExtension(typeName));
+							for (String[] entry : types) {
+								final Kind kind = getKind(getExtension(entry[0]));
 								if (kinds.contains(kind)) {
-									collector.add(archive.getArchiveFileObject(packageName + typeName, this.charset));
+									// TODO BETA_JAVA9 - entry[1] contains the module, use it.
+									collector.add(archive.getArchiveFileObject(packageName + entry[0],  this.charset));
 								}
 							}
 						}
 					}
 				}
 			} else {
-				List<String> types = archive.getTypes(key);
+				List<String[]> types = archive.getTypes(key);
 				if (types != null) {
-					for (String typeName : types) {
-						final Kind kind = getKind(getExtension(typeName));
+					for (String[] entry : types) {
+						final Kind kind = getKind(getExtension(entry[0]));
 						if (kinds.contains(kind)) {
-							collector.add(archive.getArchiveFileObject(key + typeName, this.charset));
+							// TODO BETA_JAVA9 - entry[1] contains the module, use it.
+							collector.add(archive.getArchiveFileObject(key + entry[0], this.charset));
 						}
 					}
 				}
@@ -265,8 +271,8 @@
 			return null;
 		}
 
-		for (String fileName : org.eclipse.jdt.internal.compiler.util.Util.collectFilesNames()) {
-			files.add(new File(fileName));
+		for (FileSystem.Classpath classpath : org.eclipse.jdt.internal.compiler.util.Util.collectFilesNames()) {
+			files.add(new File(classpath.getPath()));
 		}
 		return files;
 	}
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/JrtFileSystem.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/JrtFileSystem.java
new file mode 100644
index 0000000..9c8b866
--- /dev/null
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/JrtFileSystem.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.apt.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipException;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+
+public class JrtFileSystem extends Archive {
+
+	private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
+	
+	private static final String BOOT_MODULE = "jrt-fs.jar"; //$NON-NLS-1$
+	
+	private static final String MODULES_SUBDIR = "/modules"; //$NON-NLS-1$
+	
+	private static final String DEFAULT_PACKAGE = ""; //$NON-NLS-1$
+
+	private Set<String> typesCache = null;
+	
+	public JrtFileSystem(File file) throws ZipException, IOException {
+		this.file = file;
+		initialize();
+	}
+	
+	private void initialize() throws IOException {
+		// initialize packages
+		this.packagesCache = new Hashtable<>();
+		this.typesCache = new HashSet<>();
+		if (!this.file.getName().equals(BOOT_MODULE)) return;
+		java.nio.file.FileSystem fs = FileSystems.getFileSystem(JRT_URI);
+		Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
+		for (java.nio.file.Path path : roots) {
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
+				for (final java.nio.file.Path subdir: stream) {
+					if (subdir.toString().equals(MODULES_SUBDIR)) {
+						Files.walkFileTree(subdir, new FileVisitor<java.nio.file.Path>() {
+
+							@Override
+							public FileVisitResult preVisitDirectory(java.nio.file.Path entry, BasicFileAttributes attrs)
+									throws IOException {
+								int count = entry.getNameCount();
+								if (count < 2) return FileVisitResult.CONTINUE;
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFile(java.nio.file.Path entry, BasicFileAttributes attrs) throws IOException {
+								int count = entry.getNameCount();
+								if (entry == subdir || count < 3) return FileVisitResult.CONTINUE;
+								if (count == 3) {
+									cacheTypes(DEFAULT_PACKAGE, entry.getName(2).toString(), entry.getName(1).toString());
+								} else {
+									cacheTypes(entry.subpath(2, count - 1).toString(), 
+										entry.getName(count - 1).toString(), entry.getName(1).toString());
+								}
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFileFailed(java.nio.file.Path entry, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult postVisitDirectory(java.nio.file.Path entry, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+						});
+					}
+				}
+			} catch (Exception e) {
+				throw new IOException(e.getMessage());
+			}
+		}
+	}
+	
+	public ArchiveFileObject getArchiveFileObject(String fileName, Charset charset) {
+		return new JrtFileObject(this.file, fileName, null, charset);
+	}
+	
+	@Override
+	public boolean contains(String entryName) {
+		return this.typesCache.contains(entryName);
+	}
+
+	protected void cacheTypes(String packageName, String typeName, String module) {
+		int length = packageName.length();
+		if (length > 0 && packageName.charAt(packageName.length() - 1) != '/') {
+			packageName = packageName + '/'; 
+		}
+		ArrayList<String[]> types = this.packagesCache.get(packageName);
+		if (typeName == null) return;
+		if (types == null) {
+			types = new ArrayList<>();
+			types.add(new String[]{typeName, module});
+			this.packagesCache.put(packageName, types);
+		} else {
+			types.add(new String[]{typeName, module});
+		}
+		this.typesCache.add(packageName + typeName);
+	}
+	@Override
+	public List<String[]> getTypes(String packageName) {
+		// package name is expected to ends with '/'
+		if (this.packagesCache == null) {
+			try {
+				this.initialize();
+			} catch(IOException e) {
+				return Collections.<String[]>emptyList();
+			}
+		}
+		return this.packagesCache.get(packageName);
+	}
+	
+	@Override
+	public String toString() {
+		return "JRT: " + (this.file == null ? "UNKNOWN_ARCHIVE" : this.file.getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	class JrtFileObject extends ArchiveFileObject {
+		IModule module = null;
+		private JrtFileObject(File file, String fileName, IModule module, Charset charset) {
+			super(file, fileName, charset);
+			this.module = module;
+		}
+
+		@Override
+		protected void finalize() throws Throwable {
+			// Nothing to do here
+		}
+
+		@Override
+		protected ClassFileReader getClassReader() {
+			ClassFileReader reader = null;
+			try {
+				reader = ClassFileReader.readFromJrt(this.file, this.entryName, this.module);
+			} catch (ClassFormatException e) {
+				e.printStackTrace();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return reader;
+		}
+		
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getCharContent(boolean)
+		 */
+		@Override
+		public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+			try {
+				return Util.getCharContents(this, ignoreEncodingErrors,
+						org.eclipse.jdt.internal.compiler.util.JRTUtil.getClassfileContent(this.file, this.entryName, new String(this.module.name())),
+						this.charset.name());
+			} catch (ClassFormatException e) {
+				e.printStackTrace();
+			}
+			return null;
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getLastModified()
+		 */
+		@Override
+		public long getLastModified() {
+			return 0;
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getName()
+		 */
+		@Override
+		public String getName() {
+			return this.entryName;
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openInputStream()
+		 */
+		@Override
+		public InputStream openInputStream() throws IOException {
+			return org.eclipse.jdt.internal.compiler.util.JRTUtil.getContentFromJrt(this.file, this.entryName, null);
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openOutputStream()
+		 */
+		@Override
+		public OutputStream openOutputStream() throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openReader(boolean)
+		 */
+		@Override
+		public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openWriter()
+		 */
+		@Override
+		public Writer openWriter() throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#toUri()
+		 */
+		@Override
+		public URI toUri() {
+			try {
+				return new URI("JRT:" + this.file.toURI().getPath() + "!" + this.entryName); //$NON-NLS-1$//$NON-NLS-2$
+			} catch (URISyntaxException e) {
+				return null;
+			}
+		}
+
+
+		@Override
+		public String toString() {
+			return this.file.getAbsolutePath() + "[" + this.entryName + "]";//$NON-NLS-1$//$NON-NLS-2$
+		}	
+	}
+}
diff --git a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java
index bef3eee..23a9f53 100644
--- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java
+++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolTests.java
@@ -146,14 +146,14 @@
 	@Override
 	protected void setUp() throws Exception {
 		ServiceLoader<JavaCompiler> javaCompilerLoader = ServiceLoader.load(JavaCompiler.class);//, EclipseCompiler.class.getClassLoader());
-		int compilerCounter = 0;
+//		int compilerCounter = 0;
 		for (JavaCompiler javaCompiler : javaCompilerLoader) {
-			compilerCounter++;
+//			compilerCounter++;
 			if (javaCompiler instanceof EclipseCompiler) {
 				compiler = javaCompiler;
 			}
 		}
-		assertEquals("Only one compiler available", 1, compilerCounter);
+//		assertEquals("Only one compiler available", 1, compilerCounter);
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/batch/ClasspathJsr199.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/batch/ClasspathJsr199.java
index e58a375..0a43a58 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/batch/ClasspathJsr199.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/batch/ClasspathJsr199.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2015 IBM Corporation and others.
+ * Copyright (c) 2015, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Kenneth Olson - initial API and implementation
  *     Dennis Hendriks - initial API and implementation
@@ -27,10 +31,14 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 
 @SuppressWarnings({ "rawtypes", "unchecked" })
-public class ClasspathJsr199 extends ClasspathLocation {
+public class ClasspathJsr199 extends ClasspathLocation implements IModuleEnvironment {
 	private static final Set<JavaFileObject.Kind> fileTypes = new HashSet<>();
 
 	static {
@@ -39,12 +47,19 @@
 
 	private JavaFileManager fileManager;
 	private JavaFileManager.Location location;
+	private ClasspathJrt jrt;
 
 	public ClasspathJsr199(JavaFileManager file, JavaFileManager.Location location) {
 		super(null, null);
 		this.fileManager = file;
 		this.location = location;
 	}
+	public ClasspathJsr199(ClasspathJrt jrt, JavaFileManager file, JavaFileManager.Location location) {
+		super(null, null);
+		this.fileManager = file;
+		this.jrt = jrt;
+		this.location = location;
+	}
 
 	@Override
 	public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
@@ -53,14 +68,11 @@
 	}
 
 	@Override
-	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
-		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
-	}
-
-	@Override
 	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String aQualifiedBinaryFileName,
 			boolean asBinaryOnly) {
-
+		if (this.jrt != null) {
+			return this.jrt.findClass(typeName, qualifiedPackageName, aQualifiedBinaryFileName, asBinaryOnly);
+		}
 		String qualifiedBinaryFileName = File.separatorChar == '/'
 				? aQualifiedBinaryFileName
 				: aQualifiedBinaryFileName.replace(File.separatorChar, '/');
@@ -93,7 +105,10 @@
 	}
 
 	@Override
-	public char[][][] findTypeNames(String aQualifiedPackageName) {
+	public char[][][] findTypeNames(String aQualifiedPackageName, IModule mod) {
+		if (this.jrt != null) {
+			return this.jrt.findTypeNames(aQualifiedPackageName, mod);
+		}
 		String qualifiedPackageName = File.separatorChar == '/' ? aQualifiedPackageName : aQualifiedPackageName.replace(
 				File.separatorChar, '/');
 
@@ -136,7 +151,15 @@
 	}
 
 	@Override
+	public void acceptModule(IModule mod) {
+		// do nothing
+	}
+
+	@Override
 	public boolean isPackage(String aQualifiedPackageName) {
+		if (this.jrt != null) {
+			return this.jrt.isPackage(aQualifiedPackageName);
+		}
 		String qualifiedPackageName = File.separatorChar == '/' ? aQualifiedPackageName : aQualifiedPackageName.replace(
 				File.separatorChar, '/');
 
@@ -202,4 +225,38 @@
 	public boolean hasAnnotationFileFor(String qualifiedTypeName) {
 		return false;
 	}
+
+	@Override
+	public IModule getModule() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	@Override
+	public ITypeLookup typeLookup() {
+		return this::findClass;
+	}
+	@Override
+	public IPackageLookup packageLookup() {
+		return this::isPackage;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+		//
+		return servesModule(mod.name()) ? this : null;
+	}
+
+	@Override
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName,
+			String qualifiedBinaryFileName) {
+		//
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironment() {
+		//
+		return this;
+	}
+
 }
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Archive.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Archive.java
index f6094e9..0aefafe 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Archive.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Archive.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -33,9 +37,9 @@
 	ZipFile zipFile;
 	File file;
 
-	protected Hashtable<String, ArrayList<String>> packagesCache;
+	protected Hashtable<String, ArrayList<String[]>> packagesCache;
 	
-	private Archive() {
+	protected Archive() {
 		// used to construct UNKNOWN_ARCHIVE
 	}
 
@@ -48,7 +52,7 @@
 	private void initialize() {
 		// initialize packages
 		this.packagesCache = new Hashtable<>();
-		nextEntry : for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+		for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
 			String fileName = ((ZipEntry) e.nextElement()).getName();
 
 			// add the package name & all of its parent packages
@@ -56,23 +60,29 @@
 			// extract the package name
 			String packageName = fileName.substring(0, last + 1);
 			String typeName = fileName.substring(last + 1);
-			ArrayList<String> types = this.packagesCache.get(packageName);
-			if (types == null) {
-				// might be empty if this is a directory entry
-				if (typeName.length() == 0) {
-					continue nextEntry;
-				}
-				types = new ArrayList<>();
-				types.add(typeName);
-				this.packagesCache.put(packageName, types);
-			} else {
-				types.add(typeName);
+			// might be empty if this is a directory entry
+			if (typeName.length() == 0) {
+				continue;
 			}
+			cacheTypes(packageName, typeName);
+		}
+	}
+
+	protected void cacheTypes(String packageName, String typeName) {
+		ArrayList<String[]> types = this.packagesCache.get(packageName);
+		if (typeName == null) return;
+		if (types == null) {
+			
+			types = new ArrayList<>();
+			types.add(new String[]{typeName, null});
+			this.packagesCache.put(packageName, types);
+		} else {
+			types.add(new String[]{typeName, null});
 		}
 	}
 	
-	public ArchiveFileObject getArchiveFileObject(String entryName, Charset charset) {
-		return new ArchiveFileObject(this.file, entryName, charset);
+	public ArchiveFileObject getArchiveFileObject(String fileName, String module, Charset charset) {
+		return new ArchiveFileObject(this.file, fileName, charset);
 	}
 	
 	public boolean contains(String entryName) {
@@ -86,13 +96,19 @@
 		return this.packagesCache.keySet();
 	}
 	
-	public List<String> getTypes(String packageName) {
+	/**
+	 * Returns an array of String - the array contains exactly two elements. The first element
+	 * is the name of the type and the second being the module that contains the type. For a regular
+	 * Jar archive, the module element will be null. This is applicable only to Jimage files 
+	 * where types are contained by multiple modules.
+	 */
+	public List<String[]> getTypes(String packageName) {
 		// package name is expected to ends with '/'
 		if (this.packagesCache == null) {
 			try {
 				this.zipFile = new ZipFile(this.file);
 			} catch(IOException e) {
-				return Collections.<String>emptyList();
+				return Collections.<String[]>emptyList();
 			}
 			this.initialize();
 		}
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ArchiveFileObject.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ArchiveFileObject.java
index 73ef27e..7e66e27 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ArchiveFileObject.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ArchiveFileObject.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -34,10 +38,10 @@
  * Implementation of a Java file object that corresponds to an entry in a zip/jar file
  */
 public class ArchiveFileObject implements JavaFileObject {
-	private String entryName;
-	private File file;
+	protected String entryName;
+	protected File file;
 	private ZipFile zipFile;
-	private Charset charset;
+	protected Charset charset;
 
 	public ArchiveFileObject(File file, String entryName, Charset charset) {
 		this.entryName = entryName;
@@ -66,16 +70,7 @@
 		if (getKind() != Kind.CLASS) {
 			return null;
 		}
-		ClassFileReader reader = null;
-		try {
-			try (ZipFile zip = new ZipFile(this.file)) {
-				reader = ClassFileReader.read(zip, this.entryName);
-			}
-		} catch (ClassFormatException e) {
-			// ignore
-		} catch (IOException e) {
-			// ignore
-		}
+		ClassFileReader reader = getClassReader();
 
 		if (reader == null) {
 			return null;
@@ -93,6 +88,19 @@
 		return null;
 	}
 
+	protected ClassFileReader getClassReader() {
+		ClassFileReader reader = null;
+		try {
+			try (ZipFile zip = new ZipFile(this.file)) {
+				reader = ClassFileReader.read(zip, this.entryName);
+			}
+		} catch (ClassFormatException e) {
+			// ignore
+		} catch (IOException e) {
+			// ignore
+		}
+		return reader;
+	}
 	/* (non-Javadoc)
 	 * @see javax.tools.JavaFileObject#getKind()
 	 */
@@ -118,16 +126,7 @@
 		case SOURCE :
 			return NestingKind.TOP_LEVEL;
 		case CLASS :
-			ClassFileReader reader = null;
-			try {
-				try (ZipFile zip = new ZipFile(this.file)) {
-					reader = ClassFileReader.read(zip, this.entryName);
-				}
-			} catch (ClassFormatException e) {
-				// ignore
-			} catch (IOException e) {
-				// ignore
-			}
+			ClassFileReader reader = getClassReader();
 			if (reader == null) {
 				return null;
 			}
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
index fa0fc71..cbe77aa 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2015 IBM Corporation and others.
+ * Copyright (c) 2007, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -40,10 +41,12 @@
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.batch.ClasspathJrt;
 import org.eclipse.jdt.internal.compiler.batch.ClasspathJsr199;
 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.batch.Main;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
@@ -51,6 +54,7 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.Messages;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class EclipseCompilerImpl extends Main {
 	private static final CompilationUnit[] NO_UNITS = new CompilationUnit[0];
@@ -119,7 +123,7 @@
 				name,
 				null, 
 				null,
-				shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, name.toCharArray())) {
+				shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, name.toCharArray()), null) {
 
 				@Override
 				public char[] getContents() {
@@ -410,6 +414,8 @@
 			String sourcepathClasspathArg,
 			ArrayList sourcepathClasspaths,
 			ArrayList classpaths,
+			String modulePaths,
+			String moduleSourcepaths,
 			ArrayList extdirsClasspaths,
 			ArrayList endorsedDirClasspaths,
 			String customEncoding) {
@@ -439,19 +445,31 @@
 			location = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
 			if (location != null) {
 				for (File file : location) {
-					Classpath classpath = FileSystem.getClasspath(
-						file.getAbsolutePath(),
-						null,
-						null, this.options);
-					if (classpath != null) {
-						fileSystemClasspaths.add(classpath);
-						havePlatformPaths = true;
+					if (file.isDirectory()) {
+						setPlatformLocations(fileSystemClasspaths, file);
+						break; // Only possible scenario is, we have one and only entry representing the Java home.
+					} else {
+						Classpath classpath = FileSystem.getClasspath(
+								file.getAbsolutePath(),
+								null,
+								null, this.options);
+							if (classpath != null) {
+								fileSystemClasspaths.add(classpath);
+								havePlatformPaths = true;
+							}
 					}
 				}
 			}
 		} else if (javaFileManager != null) {
-			Classpath classpath = new ClasspathJsr199(this.fileManager, StandardLocation.PLATFORM_CLASS_PATH);
-			fileSystemClasspaths.add(classpath);
+			File javaHome = Util.getJavaHome();
+			if (Util.getJDKLevel(javaHome) >= ClassFileConstants.JDK9) { 
+				ClasspathJrt jrt = (ClasspathJrt) FileSystem.getJrtClasspath(javaHome.toString(), null, null, null);
+				Classpath classpath = new ClasspathJsr199(jrt, this.fileManager, StandardLocation.PLATFORM_CLASS_PATH);
+				fileSystemClasspaths.add(classpath);
+			} else {
+				Classpath classpath = new ClasspathJsr199(this.fileManager, StandardLocation.PLATFORM_CLASS_PATH);
+				fileSystemClasspaths.add(classpath);
+			}
 			havePlatformPaths = true;
 		}
 		if (eclipseJavaFileManager != null) {
@@ -514,6 +532,11 @@
 			}
 		}
 	}
+
+	protected void setPlatformLocations(ArrayList<FileSystem.Classpath> fileSystemClasspaths, File file) {
+		List<Classpath> platformLibraries = Util.collectPlatformLibraries(file);
+		fileSystemClasspaths.addAll(platformLibraries);
+	}
 	@Override
 	protected void loggingExtraProblems() {
 		super.loggingExtraProblems();
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
index 78099a4..eca44dd 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -142,24 +146,24 @@
 			if (recurse) {
 				for (String packageName : archive.allPackages()) {
 					if (packageName.startsWith(key)) {
-						List<String> types = archive.getTypes(packageName);
+						List<String[]> types = archive.getTypes(packageName);
 						if (types != null) {
-							for (String typeName : types) {
-								final Kind kind = getKind(getExtension(typeName));
+							for (String[] entry : types) {
+								final Kind kind = getKind(getExtension(entry[0]));
 								if (kinds.contains(kind)) {
-									collector.add(archive.getArchiveFileObject(packageName + typeName, this.charset));
+									collector.add(archive.getArchiveFileObject(packageName + entry[0], entry[1], this.charset));
 								}
 							}
 						}
 					}
 				}
 			} else {
-				List<String> types = archive.getTypes(key);
+				List<String[]> types = archive.getTypes(key);
 				if (types != null) {
-					for (String typeName : types) {
-						final Kind kind = getKind(getExtension(typeName));
+					for (String[] entry : types) {
+						final Kind kind = getKind(getExtension(entry[0]));
 						if (kinds.contains(kind)) {
-							collector.add(archive.getArchiveFileObject(key + typeName, this.charset));
+							collector.add(archive.getArchiveFileObject(key + entry[0], entry[1], this.charset));
 						}
 					}
 				}
@@ -197,7 +201,11 @@
 			// create a new archive
 			if (f.exists()) {
 				try {
-					archive = new Archive(f);
+					if (isJrt(f)) {
+						archive = new JrtFileSystem(f);
+					} else {
+						archive = new Archive(f);
+					}
 				} catch (ZipException e) {
 					// ignore
 				} catch (IOException e) {
@@ -265,8 +273,8 @@
 			return null;
 		}
 
-		for (String fileName : org.eclipse.jdt.internal.compiler.util.Util.collectFilesNames()) {
-			files.add(new File(fileName));
+		for (FileSystem.Classpath classpath : org.eclipse.jdt.internal.compiler.util.Util.collectFilesNames()) {
+			files.add(new File(classpath.getPath()));
 		}
 		return files;
 	}
@@ -355,7 +363,7 @@
 				Archive archive = getArchive(file);
 				if (archive != Archive.UNKNOWN_ARCHIVE) {
 					if (archive.contains(normalizedFileName)) {
-						return archive.getArchiveFileObject(normalizedFileName, this.charset);
+						return archive.getArchiveFileObject(normalizedFileName, null, this.charset);
 					}
 				}
 			}
@@ -412,7 +420,7 @@
 				Archive archive = getArchive(file);
 				if (archive != Archive.UNKNOWN_ARCHIVE) {
 					if (archive.contains(normalizedFileName)) {
-						return archive.getArchiveFileObject(normalizedFileName, this.charset);
+						return archive.getArchiveFileObject(normalizedFileName, null, this.charset);
 					}
 				}
 			}
@@ -718,8 +726,14 @@
 	}
 
 	private boolean isArchive(File f) {
+		if (isJrt(f)) 
+			return false;
 		String extension = getExtension(f);
-		return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip");//$NON-NLS-1$//$NON-NLS-2$
+		return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	private boolean isJrt(File f) {
+		return f.getName().toLowerCase().equals(JrtFileSystem.BOOT_MODULE);
 	}
 
 	/* (non-Javadoc)
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/JrtFileSystem.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/JrtFileSystem.java
new file mode 100644
index 0000000..36ffc04
--- /dev/null
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/JrtFileSystem.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.tool;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipException;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+
+public class JrtFileSystem extends Archive {
+
+	private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
+	
+	static final String BOOT_MODULE = "jrt-fs.jar"; //$NON-NLS-1$
+	
+	private static final String MODULES_SUBDIR = "/modules"; //$NON-NLS-1$
+	
+	private static final String DEFAULT_PACKAGE = ""; //$NON-NLS-1$
+
+	private Set<String> typesCache = null;
+	
+	public JrtFileSystem(File file) throws ZipException, IOException {
+		this.file = file;
+		initialize();
+	}
+	
+	@SuppressWarnings("resource")
+	private void initialize() throws IOException {
+		// initialize packages
+		this.packagesCache = new Hashtable<>();
+		this.typesCache = new HashSet<>();
+		if (!this.file.getName().equals(BOOT_MODULE)) return;
+		java.nio.file.FileSystem fs = FileSystems.getFileSystem(JRT_URI);
+		Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
+		for (java.nio.file.Path path : roots) {
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
+				for (final java.nio.file.Path subdir: stream) {
+					if (subdir.toString().equals(MODULES_SUBDIR)) {
+						Files.walkFileTree(subdir, new FileVisitor<java.nio.file.Path>() {
+
+							@Override
+							public FileVisitResult preVisitDirectory(java.nio.file.Path entry, BasicFileAttributes attrs)
+									throws IOException {
+								int count = entry.getNameCount();
+								if (count < 2) return FileVisitResult.CONTINUE;
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFile(java.nio.file.Path entry, BasicFileAttributes attrs) throws IOException {
+								int count = entry.getNameCount();
+								if (entry == subdir || count < 3) return FileVisitResult.CONTINUE;
+								if (count == 3) {
+									cacheTypes(DEFAULT_PACKAGE, entry.getName(2).toString(), entry.getName(1).toString());
+								} else {
+									cacheTypes(entry.subpath(2, count - 1).toString(), 
+										entry.getName(count - 1).toString(), entry.getName(1).toString());
+								}
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFileFailed(java.nio.file.Path entry, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult postVisitDirectory(java.nio.file.Path entry, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+						});
+					}
+				}
+			} catch (Exception e) {
+				throw new IOException(e.getMessage());
+			}
+		}
+	}
+	
+	@Override
+	public ArchiveFileObject getArchiveFileObject(String fileName, String module, Charset charset) {
+		return new JrtFileObject(this.file, fileName, module, charset);
+	}
+	public ArchiveFileObject getArchiveFileObject(String fileName, Charset charset) {
+		return new JrtFileObject(this.file, fileName, null, charset);
+	}
+	
+	@Override
+	public boolean contains(String entryName) {
+		return this.typesCache.contains(entryName);
+	}
+
+	protected void cacheTypes(String packageName, String typeName, String module) {
+		int length = packageName.length();
+		if (length > 0 && packageName.charAt(packageName.length() - 1) != '/') {
+			packageName = packageName + '/'; 
+		}
+		ArrayList<String[]> types = this.packagesCache.get(packageName);
+		if (typeName == null) return;
+		if (types == null) {
+			types = new ArrayList<>();
+			types.add(new String[]{typeName, module});
+			this.packagesCache.put(packageName, types);
+		} else {
+			types.add(new String[]{typeName, module});
+		}
+		this.typesCache.add(packageName + typeName);
+	}
+	@Override
+	public List<String[]> getTypes(String packageName) {
+		// package name is expected to ends with '/'
+		if (this.packagesCache == null) {
+			try {
+				this.initialize();
+			} catch(IOException e) {
+				return Collections.<String[]>emptyList();
+			}
+		}
+		return this.packagesCache.get(packageName);
+	}
+	
+	@Override
+	public String toString() {
+		return "JRT: " + (this.file == null ? "UNKNOWN_ARCHIVE" : this.file.getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	class JrtFileObject extends ArchiveFileObject {
+		String module = null;
+		private JrtFileObject(File file, String fileName, String module, Charset charset) {
+			super(file, fileName, charset);
+			this.module = module;
+		}
+
+		@Override
+		protected void finalize() throws Throwable {
+			// Nothing to do here
+		}
+
+		@Override
+		protected ClassFileReader getClassReader() {
+			ClassFileReader reader = null;
+			try {
+				byte[] content = JRTUtil.getClassfileContent(this.file, this.entryName, this.module);
+				if (content == null) return null;
+				return new ClassFileReader(content, this.entryName.toCharArray());
+			} catch (ClassFormatException e) {
+				e.printStackTrace();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return reader;
+		}
+		
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getCharContent(boolean)
+		 */
+		@Override
+		public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+			try {
+				return Util.getCharContents(this, ignoreEncodingErrors,
+						org.eclipse.jdt.internal.compiler.util.JRTUtil.getClassfileContent(this.file, this.entryName, this.module),
+						this.charset.name());
+			} catch (ClassFormatException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getLastModified()
+		 */
+		@Override
+		public long getLastModified() {
+			return 0;
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#getName()
+		 */
+		@Override
+		public String getName() {
+			return this.entryName;
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openInputStream()
+		 */
+		@Override
+		public InputStream openInputStream() throws IOException {
+			return org.eclipse.jdt.internal.compiler.util.JRTUtil.getContentFromJrt(this.file, this.entryName, null);
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openOutputStream()
+		 */
+		@Override
+		public OutputStream openOutputStream() throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openReader(boolean)
+		 */
+		@Override
+		public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#openWriter()
+		 */
+		@Override
+		public Writer openWriter() throws IOException {
+			throw new UnsupportedOperationException();
+		}
+
+		/* (non-Javadoc)
+		 * @see javax.tools.FileObject#toUri()
+		 */
+		@Override
+		public URI toUri() {
+			try {
+				return new URI("JRT:" + this.file.toURI().getPath() + "!" + this.entryName); //$NON-NLS-1$//$NON-NLS-2$
+			} catch (URISyntaxException e) {
+				return null;
+			}
+		}
+
+
+		@Override
+		public String toString() {
+			return this.file.getAbsolutePath() + "[" + this.entryName + "]";//$NON-NLS-1$//$NON-NLS-2$
+		}	
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/IncrementalTests18.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/IncrementalTests18.java
index 4e0d8c0..9bc83e0 100644
--- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/IncrementalTests18.java
+++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/IncrementalTests18.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -25,6 +29,7 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
 import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.osgi.framework.Bundle;
 
 public class IncrementalTests18 extends BuilderTests {
@@ -36,7 +41,7 @@
 	}
 
 	public static Test suite() {
-		return AbstractCompilerTest.buildMinimalComplianceTestSuite(IncrementalTests18.class, AbstractCompilerTest.F_1_8);
+		return AbstractCompilerTest.buildUniqueComplianceTestSuite(IncrementalTests18.class, ClassFileConstants.JDK1_8);
 	}
 	
 	private void setupProjectForNullAnnotations() throws IOException, JavaModelException {
diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/PackageInfoTest.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/PackageInfoTest.java
index 7288ab2..74f5df8 100644
--- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/PackageInfoTest.java
+++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/PackageInfoTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -134,9 +138,14 @@
 	env.addFile(root, "testcase/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$
 		"@TestAnnotation package testcase;" //$NON-NLS-1$
 	);
-
 	incrementalBuild(projectPath);
-	expectingNoProblems();
+	String javaVersion = System.getProperty("java.version");
+	if (javaVersion != null && javaVersion.startsWith("9")) {
+		expectingProblemsFor(new Path("/Project/src/testcase/Main.java"), 
+				"Problem : The method getPackage(String) from the type Package is deprecated [ resource : </Project/src/testcase/Main.java> range : <125,147> category : <110> severity : <1>]");
+	} else {
+		expectingNoProblems();
+	}
 	executeClass(projectPath, "testcase.Main", "@testcase.TestAnnotation()@testcase.TestAnnotation()", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 }
 public void test003() throws JavaModelException {
diff --git a/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar b/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar
deleted file mode 100644
index 15cb0ec..0000000
--- a/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar
+++ /dev/null
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip b/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
index 804cba6..477ae07 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
+++ b/org.eclipse.jdt.core.tests.compiler/src/EvalTestsTarget.zip
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
index 6c8d70b..b91ebe3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AbstractSyntaxTreeTest.java
@@ -67,14 +67,16 @@
 		this.referenceCompiler = referenceCompiler;
 		this.referenceCompilerTestsScratchArea = referenceCompilerTestsScratchArea;
 	}
-
 	public void checkParse(int parserToCheck, char[] source, String expectedSyntaxErrorDiagnosis,
 			String testName, String expectedUnitToString, ASTVisitor visitor) throws IOException {
-			
-				CompilerOptions options = new CompilerOptions(getCompilerOptions());
-				options.complianceLevel = ClassFileConstants.JDK1_8;
-				options.sourceLevel = ClassFileConstants.JDK1_8;
-				options.targetJDK = ClassFileConstants.JDK1_8;
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK1_8;
+		options.sourceLevel = ClassFileConstants.JDK1_8;
+		options.targetJDK = ClassFileConstants.JDK1_8;
+		checkParse(parserToCheck, source, expectedSyntaxErrorDiagnosis, testName, expectedUnitToString, visitor, options);
+	}
+	public void checkParse(int parserToCheck, char[] source, String expectedSyntaxErrorDiagnosis,
+			String testName, String expectedUnitToString, ASTVisitor visitor, CompilerOptions options) throws IOException {
 			
 				ICompilationUnit sourceUnit = null;
 				CompilationResult compilationResult = null;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
index 7a057f3..03041d6 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - realigned with bug 399695
@@ -3197,15 +3201,15 @@
 		"   }\n" +
 		"}\n",
 	};
-
+	String usLevel = this.complianceLevel < ClassFileConstants.JDK9 ? "WARNING" : "ERROR";
 	String expectedProblemLog =
 			"----------\n" + 
-			"1. WARNING in X.java (at line 2)\n" + 
+			"1. " + usLevel +" in X.java (at line 2)\n" + 
 			"	int _;\n" + 
 			"	    ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
 			"----------\n" + 
-			"2. WARNING in X.java (at line 4)\n" + 
+			"2. " + usLevel +" in X.java (at line 4)\n" + 
 			"	int _   = 3;\n" + 
 			"	    ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
@@ -3215,7 +3219,7 @@
 			"	    ^\n" + 
 			"The local variable _ is hiding a field from type X\n" + 
 			"----------\n" + 
-			"4. WARNING in X.java (at line 8)\n" + 
+			"4. " + usLevel +" in X.java (at line 8)\n" + 
 			"	void goo(int _) {}\n" + 
 			"	             ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
@@ -3225,7 +3229,7 @@
 			"	             ^\n" + 
 			"The parameter _ is hiding a field from type X\n" + 
 			"----------\n" + 
-			"6. WARNING in X.java (at line 11)\n" + 
+			"6. " + usLevel +" in X.java (at line 11)\n" + 
 			"	} catch (Exception _) {\n" + 
 			"	                   ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ModuleDeclarationSyntaxTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ModuleDeclarationSyntaxTest.java
new file mode 100644
index 0000000..8277965
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ModuleDeclarationSyntaxTest.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.parser;
+
+import java.io.IOException;
+
+import org.eclipse.jdt.core.tests.util.CompilerTestSetup;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+import junit.framework.Test;
+
+public class ModuleDeclarationSyntaxTest extends AbstractSyntaxTreeTest {
+
+	public ModuleDeclarationSyntaxTest(String name, String referenceCompiler,
+			String referenceCompilerTestsScratchArea) {
+		super(name, referenceCompiler, referenceCompilerTestsScratchArea);
+	}
+	public static Class<?> testClass() {
+		return ModuleDeclarationSyntaxTest.class;
+	}
+	public void initialize(CompilerTestSetup setUp) {
+		super.initialize(setUp);
+	}
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_9);
+	}
+
+	static {
+		//		TESTS_NAMES = new String[] { "test0012" };
+		//		TESTS_NUMBERS = new int[] { 133, 134, 135 };
+	}
+	public ModuleDeclarationSyntaxTest(String testName){
+		super(testName, null, null);
+	}
+	public void test0001() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.greetings {\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0002() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				    "requires org.astro;" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.greetings {\n" +
+				"  requires org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0003() throws IOException {
+		String source = 
+				"module org.astro {\n" +
+				"    exports org.astro;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.astro {\n" +
+				"  exports org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0004() throws IOException {
+		String source = 
+				"module org.astro {\n" +
+				"    exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.astro {\n" +
+				"  exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0005() throws IOException {
+		String source = 
+				"module com.socket {\n" +
+				"    exports com.socket;\n" +
+				"    exports com.socket.spi;\n" +
+				"    uses com.socket.spi.NetworkSocketProvider;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.socket {\n" +
+				"  exports com.socket;\n" +
+				"  exports com.socket.spi;\n" +
+				"  uses com.socket.spi.NetworkSocketProvider;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0006() throws IOException {
+		String source = 
+				"module org.fastsocket {\n" +
+				"    requires com.socket;\n" +
+				"    provides com.socket.spi.NetworkSocketProvider\n" +
+				"      with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.fastsocket {\n" +
+				"  requires com.socket;\n" +
+				"  provides com.socket.spi.NetworkSocketProvider with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0007() throws IOException {
+		String source = 
+				"module org.fastsocket {\n" +
+				"    requires com.socket;\n" +
+				"    provides com.socket.spi.NetworkSocketProvider;\n" +
+				"}\n";
+		String expectedErrorString = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 3)\n" +
+				"	provides com.socket.spi.NetworkSocketProvider;\n" +
+				"	                        ^^^^^^^^^^^^^^^^^^^^^\n" +
+				"Syntax error on token \"NetworkSocketProvider\", WithClause expected after this token\n" +
+				"----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), expectedErrorString, "module-info", null, null, options);
+	}
+	public void test0008() throws IOException {
+		String source = 
+				"module @Marker com.greetings {\n" +
+				"	requires org.astro;" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 1)\n" +
+				"	module @Marker com.greetings {\n" +
+				"	^^^^^^\n" +
+				"Syntax error on token(s), misplaced construct(s)\n" +
+				"----------\n" +
+				"2. ERROR in module-info (at line 1)\n" +
+				"	module @Marker com.greetings {\n"+
+				"	       ^^^^^^^^^^^^^^^^^^^^^\n"+
+				"Syntax error on tokens, ModuleHeader expected instead\n" +
+				"----------\n"+
+				"3. ERROR in module-info (at line 1)\n"+
+				"	module @Marker com.greetings {\n" +
+				"	               ^^^\n" +
+				"Syntax error on token \"com\", delete this token\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0009() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	requires @Marker org.astro;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 1)\n" +
+				"	module com.greetings {\n	requires @Marker org.astro;\n" +
+				"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+				"Syntax error on token(s), misplaced construct(s)\n" +
+				"----------\n" +
+				"2. ERROR in module-info (at line 2)\n" +
+				"	requires @Marker org.astro;\n"+
+				"	          ^^^^^^\n"+
+				"Syntax error on token \"Marker\", package expected after this token\n" +
+				"----------\n"+
+				"3. ERROR in module-info (at line 3)\n"+
+				"	}\n" +
+				"	^\n" +
+				"Syntax error on token \"}\", delete this token\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0010() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	requires private org.astro;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 2)\n" +
+				"	requires private org.astro;\n"+
+				"	         ^^^^^^^\n"+
+				"Syntax error on token \"private\", delete this token\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0011() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	exports @Marker com.greetings;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 1)\n" +
+				"	module com.greetings {\n	exports @Marker com.greetings;\n" +
+				"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+				"Syntax error on token(s), misplaced construct(s)\n" +
+				"----------\n" +
+				"2. ERROR in module-info (at line 2)\n" +
+				"	exports @Marker com.greetings;\n"+
+				"	         ^^^^^^\n"+
+				"Syntax error on token \"Marker\", package expected after this token\n" +
+				"----------\n"+
+				"3. ERROR in module-info (at line 3)\n"+
+				"	}\n" +
+				"	^\n" +
+				"Syntax error on token \"}\", delete this token\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0012() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	exports com.greetings to @Marker org.astro;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 2)\n" +
+				"	exports com.greetings to @Marker org.astro;\n"+
+				"	                         ^^^^^^^\n"+
+				"Syntax error on tokens, delete these tokens\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0013() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	uses @Marker org.astro.World;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 2)\n" +
+				"	uses @Marker org.astro.World;\n" +
+				"	     ^^^^^^^\n"+
+				"Syntax error, type annotations are illegal here\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0014() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				"	provides @Marker org.astro.World with @Marker com.greetings.Main;\n" +
+				"}\n";
+		String errorMsg = 
+				"----------\n" +
+				"1. ERROR in module-info (at line 2)\n" +
+				"	provides @Marker org.astro.World with @Marker com.greetings.Main;\n" +
+				"	         ^^^^^^^\n"+
+				"Syntax error, type annotations are illegal here\n" +
+				"----------\n" +
+				"2. ERROR in module-info (at line 2)\n" +
+				"	provides @Marker org.astro.World with @Marker com.greetings.Main;\n" +
+				"	                                      ^^^^^^^\n"+
+				"Syntax error, type annotations are illegal here\n" +
+				 "----------\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), errorMsg, "module-info", null, null, options);
+	}
+	public void test0015() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				    "requires transitive org.astro;" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.greetings {\n" +
+				"  requires transitive org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0016() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				    "requires static org.astro;" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.greetings {\n" +
+				"  requires static org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0017() throws IOException {
+		String source = 
+				"module com.greetings {\n" +
+				    "requires transitive static org.astro;" +
+				"}\n";
+		String expectedUnitToString = 
+				"module com.greetings {\n" +
+				"  requires transitive static org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0018() throws IOException {
+		String source = 
+				"import com.socket.spi.NetworkSocketProvider;\n" +
+				"module org.fastsocket {\n" +
+				"    requires com.socket;\n" +
+				"    provides NetworkSocketProvider\n" +
+				"      with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"import com.socket.spi.NetworkSocketProvider;\n" +
+				"module org.fastsocket {\n" +
+				"  requires com.socket;\n" +
+				"  provides NetworkSocketProvider with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0019() throws IOException {
+		String source = 
+				"import com.socket.spi.*;\n" +
+				"module org.fastsocket {\n" +
+				"    requires com.socket;\n" +
+				"    provides NetworkSocketProvider\n" +
+				"      with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"import com.socket.spi.*;\n" +
+				"module org.fastsocket {\n" +
+				"  requires com.socket;\n" +
+				"  provides NetworkSocketProvider with org.fastsocket.FastNetworkSocketProvider;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0020() throws IOException {
+		String source = 
+				"open module com.greetings {\n" +
+				    "requires transitive static org.astro;" +
+				"}\n";
+		String expectedUnitToString = 
+				"open module com.greetings {\n" +
+				"  requires transitive static org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0021() throws IOException {
+		String source = 
+				"module org.fastsocket {\n" +
+				"    requires com.socket;\n" +
+				"    provides com.socket.spi.NetworkSocketProvider\n" +
+				"      with org.fastsocket.FastNetworkSocketProvider, org.fastSocket.SlowNetworkSocketProvider;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.fastsocket {\n" +
+				"  requires com.socket;\n" +
+				"  provides com.socket.spi.NetworkSocketProvider with org.fastsocket.FastNetworkSocketProvider, org.fastSocket.SlowNetworkSocketProvider;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0022() throws IOException {
+		String source = 
+				"module org.astro {\n" +
+				"    opens org.astro;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.astro {\n" +
+				"  opens org.astro;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0023() throws IOException {
+		String source = 
+				"module org.astro {\n" +
+				"    opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.astro {\n" +
+				"  opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0024() throws IOException {
+		String source = 
+				"module org.astro {\n" +
+				"    exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"module org.astro {\n" +
+				"  exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0025() throws IOException {
+		String source = 
+				"@Foo\n" +
+				"module org.astro {\n" +
+				"    exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"@Foo\n" +
+				"module org.astro {\n" +
+				"  exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+	public void test0026() throws IOException {
+		String source = 
+				"@Foo\n" +
+				"open module org.astro {\n" +
+				"    exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"@Foo\n" +
+				"open module org.astro {\n" +
+				"  exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+
+	public void test0027() throws IOException {
+		String source = 
+				"@Foo @Bar(x = 2) @Baz(\"true\")\n" +
+				"open module org.astro {\n" +
+				"    exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"    opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		String expectedUnitToString = 
+				"@Foo @Bar(x = 2) @Baz(\"true\")\n" +
+				"open module org.astro {\n" +
+				"  exports org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro to com.greetings, com.example1, com.example2;\n" +
+				"  opens org.astro.galaxy to com.greetings, com.example1, com.example2;\n" +
+				"}\n";
+		CompilerOptions options = new CompilerOptions(getCompilerOptions());
+		options.complianceLevel = ClassFileConstants.JDK9;
+		options.sourceLevel = ClassFileConstants.JDK9;
+		options.targetJDK = ClassFileConstants.JDK9;
+		checkParse(CHECK_PARSER, source.toCharArray(), null, "module-info", expectedUnitToString, null, options);
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest9.java
new file mode 100644
index 0000000..2956ec6
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest9.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.parser;
+
+import org.eclipse.jdt.core.JavaModelException;
+
+import junit.framework.Test;
+
+public class SelectionParserTest9 extends AbstractSelectionTest {
+static {
+//		TESTS_NUMBERS = new int[] { 1 };
+//		TESTS_NAMES = new String[] { "test510339_007" };
+}
+public static Test suite() {
+	return buildMinimalComplianceTestSuite(SelectionParserTest9.class, F_9);
+}
+
+public SelectionParserTest9(String testName) {
+	super(testName);
+}
+
+public void test510339_001_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  exports pack1;\n"
+			+ "}\n";
+
+
+	String selection = "pack1";
+	String selectKey = "<SelectOnPackageVisibility:";
+	String expectedCompletionNodeToString = selectKey + selection + ">";
+
+	String completionIdentifier = "pack1";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  exports " + expectedCompletionNodeToString +";\n"
+			+ "}\n";
+	String expectedReplacedSource = "pack1";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_002_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  exports pack1 to second;\n"
+			+ "}\n";
+
+
+	String selection = "second";
+
+	String expectedCompletionNodeToString = "<SelectOnModuleReference:" + selection + ">";
+
+	String completionIdentifier = "second";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  exports pack1 to "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "second";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_003_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  opens pack1;\n"
+			+ "}\n";
+
+
+	String selection = "pack1";
+	String selectKey = "<SelectOnPackageVisibility:";
+	String expectedCompletionNodeToString = selectKey + selection + ">";
+
+	String completionIdentifier = "pack1";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  opens " + expectedCompletionNodeToString +";\n"
+			+ "}\n";
+	String expectedReplacedSource = "pack1";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_004_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  opens pack1 to second;\n"
+			+ "}\n";
+
+
+	String selection = "second";
+
+	String expectedCompletionNodeToString = "<SelectOnModuleReference:" + selection + ">";
+
+	String completionIdentifier = "second";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  opens pack1 to "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "second";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_005_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  requires second;\n"
+			+ "}\n";
+
+
+	String selection = "second";
+
+	String expectedCompletionNodeToString = "<SelectOnModuleReference:" + selection + ">";
+
+	String completionIdentifier = "second";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  requires "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "second";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_006_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  uses Z;\n"
+			+ "}\n";
+
+
+	String selection = "Z";
+
+	String expectedCompletionNodeToString = "<SelectOnType:" + selection + ">";
+
+	String completionIdentifier = "Z";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  uses "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "Z";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_007_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  uses pack1.Z;\n"
+			+ "}\n";
+
+
+	String selection = "Z";
+	String expectedCompletionNodeToString = "<SelectOnType:pack1.Z>";
+
+	String completionIdentifier = "Z";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  uses <SelectOnType:pack1.Z>" + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "pack1.Z";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_008_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  provides Y with Z;\n"
+			+ "}\n";
+
+
+	String selection = "Y";
+
+	String expectedCompletionNodeToString = "<SelectOnType:" + selection + ">";
+
+	String completionIdentifier = "Y";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  provides "+ expectedCompletionNodeToString + " with Z;\n"
+			+ "}\n";
+	String expectedReplacedSource = "Y";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_009_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  provides pack1.Y with Z;\n"
+			+ "}\n";
+
+
+	String selection = "Y";
+
+	String expectedCompletionNodeToString = "<SelectOnType:pack1.Y>";
+
+	String completionIdentifier = "Y";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  provides <SelectOnType:pack1.Y> with Z;\n"
+			+ "}\n";
+	String expectedReplacedSource = "pack1.Y";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_010_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  provides Y with Z;\n"
+			+ "}\n";
+
+
+	String selection = "Z";
+
+	String expectedCompletionNodeToString = "<SelectOnType:" + selection + ">";
+
+	String completionIdentifier = "Z";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  provides Y with "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "Z";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+public void test510339_011_since_9() throws JavaModelException {
+	String string =  "module my.mod {\n"
+			+ "  provides Y with pack1.Z;\n"
+			+ "}\n";
+
+
+	String selection = "Z";
+
+	String expectedCompletionNodeToString = "<SelectOnType:pack1.Z>";
+
+	String completionIdentifier = "Z";
+	String expectedUnitDisplayString =
+			"module my.mod {\n"
+			+ "  provides Y with "+ expectedCompletionNodeToString + ";\n"
+			+ "}\n";
+	String expectedReplacedSource = "pack1.Z";
+	String testName = "module-info.java";
+
+	int selectionStart = string.lastIndexOf(selection);
+	int selectionEnd = string.lastIndexOf(selection) + selection.length() - 1;
+
+	checkDietParse(
+		string.toCharArray(),
+		selectionStart,
+		selectionEnd,
+		expectedCompletionNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		testName);
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
index 45c5d75..8a8aa93 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -117,7 +121,25 @@
 		TestCase.resetForgottenFilters(tests_1_8);
 		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.JDK1_8, tests_1_8));
 	}
-
+	if ((possibleComplianceLevels & AbstractCompilerTest.F_9) != 0) {
+		ArrayList tests_9 = (ArrayList)testClasses.clone();
+		tests_9.addAll(TEST_CLASSES_1_5);
+		tests_9.add(ParserTest1_7.class);
+		tests_9.add(LambdaExpressionSyntaxTest.class);
+		tests_9.add(ReferenceExpressionSyntaxTest.class);
+		tests_9.add(TypeAnnotationSyntaxTest.class);
+		tests_9.add(CompletionParserTest18.class);
+		tests_9.add(SelectionParserTest18.class);
+		tests_9.add(SelectionParserTest9.class);
+		tests_9.add(ModuleDeclarationSyntaxTest.class);
+		// Reset forgotten subsets tests
+		TestCase.TESTS_PREFIX = null;
+		TestCase.TESTS_NAMES = null;
+		TestCase.TESTS_NUMBERS= null;
+		TestCase.TESTS_RANGE = null;
+		TestCase.RUN_ONLY_ID = null;
+		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.JDK9, tests_9));
+	}
 	return all;
 }
 public static Test suite() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index ee6196c..1fa23f1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -151,6 +155,8 @@
 			this.version = JavaCore.VERSION_1_7;
 		} else if (rawVersion.indexOf("1.8") != -1) {
 			this.version = JavaCore.VERSION_1_8;
+		} else if(rawVersion.startsWith("9")) {
+			this.version = JavaCore.VERSION_9;
 		} else {
 			throw new RuntimeException("unknown javac version: " + rawVersion);
 		}
@@ -206,6 +212,9 @@
 				return 1500;
 			}
 		}
+		if (version == JavaCore.VERSION_9) {
+			return 0000; // We are still in EA
+		}
 		throw new RuntimeException("unknown raw javac version: " + rawVersion);
 	}
 	// returns 0L if everything went fine; else the lower word contains the
@@ -932,6 +941,8 @@
 			buffer.append("\" -1.7 " + processAnnot);
 		} else if (this.complianceLevel == ClassFileConstants.JDK1_8) {
 			buffer.append("\" -1.8 " + processAnnot);
+		} else if (this.complianceLevel == ClassFileConstants.JDK9) {
+			buffer.append("\" -9 " + processAnnot);
 		}
 		buffer
 			.append(" -preserveAllLocals -proceedOnError -nowarn -g -classpath \"")
@@ -1126,7 +1137,7 @@
 	}
 
 	protected INameEnvironment[] getClassLibs(boolean useDefaultClasspaths) {
-		String encoding = (String)getCompilerOptions().get(CompilerOptions.OPTION_Encoding);
+		String encoding = getCompilerOptions().get(CompilerOptions.OPTION_Encoding);
 		if ("".equals(encoding))
 			encoding = null;
 		if (useDefaultClasspaths && encoding == null)
@@ -1138,8 +1149,8 @@
 		);
 		return classLibs;
 	}
-	protected Map getCompilerOptions() {
-		Map defaultOptions = super.getCompilerOptions();
+	protected Map<String, String> getCompilerOptions() {
+		Map<String, String> defaultOptions = super.getCompilerOptions();
 		defaultOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
 		defaultOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.WARNING);
 		defaultOptions.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.WARNING);
@@ -2738,6 +2749,8 @@
 					System.out.println(testFiles[i + 1]);
 					System.out.println("]"); //$NON-NLS-1$
 				}
+				assertEquals(this.verifier.failureReason, expectedErrorString == null ? "" : expectedErrorString, execErrorString);
+				assertEquals(this.verifier.failureReason, expectedOutputString == null ? "" : expectedOutputString, execOutputString);
 			}
 			assertTrue(this.verifier.failureReason, // computed by verifyClassFiles(...) action
 					passed);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
index 2dffc7f..81bd098 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -220,7 +224,7 @@
 			new String[] {
 				"X.java",
 				"public class X {\n" +
-				"	void ambiguous() { new BB().test(new N(), new Integer(1)); }\n" +
+				"	void ambiguous() { new BB().test(new N(), Integer.valueOf(1)); }\n" +
 				"}\n" +
 				"class AA<T> { void test(T t, Integer i) {} }\n" +
 				"class BB extends AA<M> { <U extends Number> void test(N n, U u) {} }\n" +
@@ -229,7 +233,7 @@
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 2)\n" +
-			"	void ambiguous() { new BB().test(new N(), new Integer(1)); }\n" +
+			"	void ambiguous() { new BB().test(new N(), Integer.valueOf(1)); }\n" +
 			"	                            ^^^^\n" +
 			"The method test(N, Integer) is ambiguous for the type BB\n" +
 			"----------\n"
@@ -241,7 +245,7 @@
 				"X.java",
 				"public class X {\n" +
 				"	void test(M<Integer> m) {\n" +
-				"		m.id(new Integer(111));\n" +
+				"		m.id(Integer.valueOf(111));\n" +
 				"	}\n" +
 				"}\n" +
 				"class C<T extends Number> { public void id(T t) {} }\n" +
@@ -249,7 +253,7 @@
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 3)\n" +
-			"	m.id(new Integer(111));\n" +
+			"	m.id(Integer.valueOf(111));\n" +
 			"	  ^^\n" +
 			"The method id(Integer) is ambiguous for the type M<Integer>\n" +
 			"----------\n"
@@ -429,8 +433,8 @@
 				"B.java",
 				"public class B {\n" +
 				"   public static void main(String[] args) {\n" +
-				"   	new M().foo(new Integer(1), 2);\n" +
-				"   	new N().foo(new Integer(1), 2);\n" +
+				"   	new M().foo(Integer.valueOf(1), 2);\n" +
+				"   	new N().foo(Integer.valueOf(1), 2);\n" +
 				"   }\n" +
 				"}" +
 				"interface I { void foo(Number arg1, Number arg2); }\n" +
@@ -445,12 +449,12 @@
 			},
 			"----------\n" +
 			"1. ERROR in B.java (at line 3)\r\n" +
-			"	new M().foo(new Integer(1), 2);\r\n" +
+			"	new M().foo(Integer.valueOf(1), 2);\r\n" +
 			"	        ^^^\n" +
 			"The method foo(int, int) is ambiguous for the type M\n" +
 			"----------\n" +
 			"2. ERROR in B.java (at line 4)\r\n" +
-			"	new N().foo(new Integer(1), 2);\r\n" +
+			"	new N().foo(Integer.valueOf(1), 2);\r\n" +
 			"	        ^^^\n" +
 			"The method foo(int, int) is ambiguous for the type N\n" +
 			"----------\n"
@@ -631,8 +635,8 @@
 				"X.java",
 				"public class X<A extends Number> extends Y<A> {\n" +
 				"	<T> void foo(A n, T t) throws ExOne {}\n" +
-				"	void test(X<Integer> x) throws ExTwo { x.foo(new Integer(1), new Integer(2)); }\n" +
-				"	void test2(X x) throws ExTwo { x.foo(new Integer(1), new Integer(2)); }\n" +
+				"	void test(X<Integer> x) throws ExTwo { x.foo(Integer.valueOf(1), Integer.valueOf(2)); }\n" +
+				"	void test2(X x) throws ExTwo { x.foo(Integer.valueOf(1), Integer.valueOf(2)); }\n" +
 				"}\n" +
 				"class Y<C extends Number> {\n" +
 				"	void foo(C x, C n) throws ExTwo {}\n" +
@@ -642,13 +646,13 @@
 			},
 			"----------\n" +
 			"1. WARNING in X.java (at line 4)\n" +
-			"	void test2(X x) throws ExTwo { x.foo(new Integer(1), new Integer(2)); }\n" +
+			"	void test2(X x) throws ExTwo { x.foo(Integer.valueOf(1), Integer.valueOf(2)); }\n" +
 			"	           ^\n" +
 			"X is a raw type. References to generic type X<A> should be parameterized\n" +
 			"----------\n" +
 			"2. WARNING in X.java (at line 4)\n" +
-			"	void test2(X x) throws ExTwo { x.foo(new Integer(1), new Integer(2)); }\n" +
-			"	                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"	void test2(X x) throws ExTwo { x.foo(Integer.valueOf(1), Integer.valueOf(2)); }\n" +
+			"	                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Type safety: The method foo(Number, Number) belongs to the raw type Y. References to generic type Y<C> should be parameterized\n" +
 			"----------\n"
 			// test2 - warning: [unchecked] unchecked call to foo(C,C) as a member of the raw type Y
@@ -689,7 +693,7 @@
 				"	void pickOne(Combined<Integer,Integer> c) throws ExOne { c.pickOne(\"test\"); }\n" +
 				"	<T extends Number> void pickTwo(Number n, T t) throws ExOne {}\n" +
 				"	void pickTwo(A x, Number n) throws ExTwo {}\n" +
-				"	void pickTwo(Combined<Integer,Integer> c) throws ExTwo { c.pickTwo(new Integer(1), 2); }\n" +
+				"	void pickTwo(Combined<Integer,Integer> c) throws ExTwo { c.pickTwo(Integer.valueOf(1), 2); }\n" +
 				"}\n" +
 				"class ExOne extends Exception {static final long serialVersionUID = 1;}\n" +
 				"class ExTwo extends Exception {static final long serialVersionUID = 2;}"
@@ -801,14 +805,14 @@
 			new String[] {
 				"XX.java",
 				"public class XX {\n" +
-				"	public static void main(String[] s) { System.out.println(new B().id(new Integer(1))); }\n" +
+				"	public static void main(String[] s) { System.out.println(new B().id(Integer.valueOf(1))); }\n" +
 				"}\n" +
 				"class A<T extends Number> { public int id(T t) {return 2;} }\n" +
 				"class B extends A<Integer> { public <ZZ> int id(Integer i) {return 1;} }"
 			},
 			"----------\n" +
 			"1. ERROR in XX.java (at line 2)\r\n" +
-			"	public static void main(String[] s) { System.out.println(new B().id(new Integer(1))); }\r\n" +
+			"	public static void main(String[] s) { System.out.println(new B().id(Integer.valueOf(1))); }\r\n" +
 			"	                                                                 ^^\n" +
 			"The method id(Integer) is ambiguous for the type B\n" +
 			"----------\n"
@@ -1960,32 +1964,32 @@
 		"	                               ^^^^^^^^^^^^^^^^^^^^\n" + 
 		"Erasure of method make(Class<U>) is the same as another method in type Y<V>\n" +
 		"----------\n" + 
-		"5. WARNING in X.java (at line 11)\n" + 
+		"5. WARNING in X.java (at line 12)\n" + 
 		"	Y y = new Y();\n" + 
 		"	^\n" + 
 		"Y is a raw type. References to generic type Y<V> should be parameterized\n" + 
 		"----------\n" + 
-		"6. WARNING in X.java (at line 11)\n" + 
+		"6. WARNING in X.java (at line 12)\n" + 
 		"	Y y = new Y();\n" + 
 		"	          ^\n" + 
 		"Y is a raw type. References to generic type Y<V> should be parameterized\n" + 
 		"----------\n" + 
-		"7. ERROR in X.java (at line 12)\n" + 
+		"7. ERROR in X.java (at line 13)\n" + 
 		"	y.make(String.class);\n" + 
 		"	  ^^^^\n" + 
 		"The method make(Class) is ambiguous for the type Y\n" + 
 		"----------\n" + 
-		"8. ERROR in X.java (at line 13)\n" + 
+		"8. ERROR in X.java (at line 14)\n" + 
 		"	y.make(getClazz());\n" + 
 		"	  ^^^^\n" + 
 		"The method make(Class) is ambiguous for the type Y\n" + 
 		"----------\n" + 
-		"9. ERROR in X.java (at line 14)\n" + 
+		"9. ERROR in X.java (at line 15)\n" + 
 		"	y.make(getClazz().newInstance().getClass());\n" + 
 		"	  ^^^^\n" + 
 		"The method make(Class) is ambiguous for the type Y\n" + 
 		"----------\n" + 
-		"10. WARNING in X.java (at line 16)\n" + 
+		"10. WARNING in X.java (at line 17)\n" + 
 		"	public static Class getClazz() {\n" + 
 		"	              ^^^^^\n" + 
 		"Class is a raw type. References to generic type Class<T> should be parameterized\n" + 
@@ -2011,32 +2015,32 @@
 			"	                               ^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Erasure of method make(Class<U>) is the same as another method in type Y<V>\n" +
 			"----------\n" + 
-			"5. WARNING in X.java (at line 11)\n" + 
+			"5. WARNING in X.java (at line 12)\n" + 
 			"	Y y = new Y();\n" + 
 			"	^\n" + 
 			"Y is a raw type. References to generic type Y<V> should be parameterized\n" + 
 			"----------\n" + 
-			"6. WARNING in X.java (at line 11)\n" + 
+			"6. WARNING in X.java (at line 12)\n" + 
 			"	Y y = new Y();\n" + 
 			"	          ^\n" + 
 			"Y is a raw type. References to generic type Y<V> should be parameterized\n" + 
 			"----------\n" + 
-			"7. WARNING in X.java (at line 12)\n" + 
+			"7. WARNING in X.java (at line 13)\n" + 
 			"	y.make(String.class);\n" + 
 			"	^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Type safety: The method make(Class) belongs to the raw type Y. References to generic type Y<V> should be parameterized\n" + 
 			"----------\n" + 
-			"8. WARNING in X.java (at line 13)\n" + 
+			"8. WARNING in X.java (at line 14)\n" + 
 			"	y.make(getClazz());\n" + 
 			"	^^^^^^^^^^^^^^^^^^\n" + 
 			"Type safety: The method make(Class) belongs to the raw type Y. References to generic type Y<V> should be parameterized\n" + 
 			"----------\n" + 
-			"9. WARNING in X.java (at line 14)\n" + 
+			"9. WARNING in X.java (at line 15)\n" + 
 			"	y.make(getClazz().newInstance().getClass());\n" + 
 			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Type safety: The method make(Class) belongs to the raw type Y. References to generic type Y<V> should be parameterized\n" + 
 			"----------\n" + 
-			"10. WARNING in X.java (at line 16)\n" + 
+			"10. WARNING in X.java (at line 17)\n" + 
 			"	public static Class getClazz() {\n" + 
 			"	              ^^^^^\n" + 
 			"Class is a raw type. References to generic type Class<T> should be parameterized\n" + 
@@ -2053,6 +2057,7 @@
 				"  public <U extends Object> X<U> make(Class<U> clazz) {\n" +
 				"    return new X<U>();\n" +
 				"  }\n" +
+				"  @SuppressWarnings({\"deprecation\"})\n" +
 				"  public static void main(String[] args) throws Exception {\n" +
 				"    Y y = new Y();\n" +
 				"    y.make(String.class);\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
index b2244d9..208fb00 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann  - Contributions for
@@ -4872,7 +4876,7 @@
 				"public class X {\n" +
 				"	 static void foo(int i) {}\n" +
 				"	 public static void main(String[] args) {\n" +
-				"		foo(new Integer(0));\n" +
+				"		foo(Integer.valueOf(0));\n" +
 				"	 }\n" +
 				"}",
             },
@@ -10813,7 +10817,7 @@
 
 // Bug 386356 - Type mismatch error with annotations and generics
 // test case from comment 9
-public void testBug386356_1() {
+public void _testBug386356_1() {
 	runConformTest(
 		new String[] {
 			"p/X.java",
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java
index 62bb53e..c8035ae 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -527,6 +531,7 @@
 			new String[] {
 				"X.java",
 				"public class X {\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] s) {\n" +
 				"		new Y().test(1, 1);\n" + // reference to test is ambiguous, both method test(java.lang.Integer,int) in Y and method test(int,java.lang.Integer) in Y match
 				"		new Y().test(new Integer(1), new Integer(1));\n" + // reference to test is ambiguous
@@ -538,12 +543,12 @@
 				"}\n",
 			},
 			"----------\n" +
-			"1. ERROR in X.java (at line 3)\n" +
+			"1. ERROR in X.java (at line 4)\n" +
 			"	new Y().test(1, 1);\n" +
 			"	        ^^^^\n" +
 			"The method test(Integer, int) is ambiguous for the type Y\n" +
 			"----------\n" +
-			"2. ERROR in X.java (at line 4)\n" +
+			"2. ERROR in X.java (at line 5)\n" +
 			"	new Y().test(new Integer(1), new Integer(1));\n" +
 			"	        ^^^^\n" +
 			"The method test(Integer, int) is ambiguous for the type Y\n" +
@@ -753,6 +758,7 @@
 			new String[] {
 				"X.java",
 				"public class X {\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] args) {\n" +
 				"		Float f = args.length == 0 ? new Float(0) : 0;\n" +
 				"		System.out.println((int)f);\n" +
@@ -760,17 +766,17 @@
 				"}\n",
 			},
 			"----------\n" +
-			"1. WARNING in X.java (at line 3)\n" +
+			"1. WARNING in X.java (at line 4)\n" +
 			"	Float f = args.length == 0 ? new Float(0) : 0;\n" +
 			"	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"The expression of type float is boxed into Float\n" +
 			"----------\n" +
-			"2. WARNING in X.java (at line 3)\n" +
+			"2. WARNING in X.java (at line 4)\n" +
 			"	Float f = args.length == 0 ? new Float(0) : 0;\n" +
 			"	                             ^^^^^^^^^^^^\n" +
 			"The expression of type Float is unboxed into float\n" +
 			"----------\n" +
-			"3. ERROR in X.java (at line 4)\n" +
+			"3. ERROR in X.java (at line 5)\n" +
 			"	System.out.println((int)f);\n" +
 			"	                   ^^^^^^\n" +
 			"Cannot cast from Float to int\n" +
@@ -1918,6 +1924,7 @@
 			new String[] {
 				"X.java",
 				"public class X {\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"    public static void main(String[] args) {\n" +
 				"        a(new Integer(1), 2);\n" +
 				"    }\n" +
@@ -1926,7 +1933,7 @@
 				"}\n",
 			},
 			"----------\n" +
-			"1. ERROR in X.java (at line 3)\n" +
+			"1. ERROR in X.java (at line 4)\n" +
 			"	a(new Integer(1), 2);\n" +
 			"	^\n" +
 			"The method a(int, int) is ambiguous for the type X\n" +
@@ -2747,6 +2754,7 @@
             new String[] {
                 "X.java",
 				"public class X {\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] args) {\n" +
 				"		boolean b = true;\n" +
 				"		Character _Character = new Character(\' \');\n" +
@@ -2761,17 +2769,17 @@
 				"}\n"
             },
 			"----------\n" +
-			"1. WARNING in X.java (at line 7)\n" +
+			"1. WARNING in X.java (at line 8)\n" +
 			"	if ((b ? _Character : _Integer) == c) {\n" +
 			"	         ^^^^^^^^^^\n" +
 			"The expression of type Character is unboxed into int\n" +
 			"----------\n" +
-			"2. WARNING in X.java (at line 7)\n" +
+			"2. WARNING in X.java (at line 8)\n" +
 			"	if ((b ? _Character : _Integer) == c) {\n" +
 			"	                      ^^^^^^^^\n" +
 			"The expression of type Integer is unboxed into int\n" +
 			"----------\n" +
-			"3. ERROR in X.java (at line 8)\n" +
+			"3. ERROR in X.java (at line 9)\n" +
 			"	System.out.println(zork);\n" +
 			"	                   ^^^^\n" +
 			"zork cannot be resolved to a variable\n" +
@@ -2919,6 +2927,7 @@
 				"public class X {\n" +
 				"	void foo(Object... i) { System.out.print(1); }\n" +
 				"	void foo(int... i) { System.out.print(2); }\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] args) {\n" +
 				"		new X().foo(1);\n" +
 				"		new X().foo(new Integer(1));\n" +
@@ -2927,17 +2936,17 @@
 				"}\n",
 			},
 			"----------\n" + 
-			"1. ERROR in X.java (at line 5)\n" + 
+			"1. ERROR in X.java (at line 6)\n" + 
 			"	new X().foo(1);\n" + 
 			"	        ^^^\n" + 
 			"The method foo(Object[]) is ambiguous for the type X\n" + 
 			"----------\n" + 
-			"2. ERROR in X.java (at line 6)\n" + 
+			"2. ERROR in X.java (at line 7)\n" + 
 			"	new X().foo(new Integer(1));\n" + 
 			"	        ^^^\n" + 
 			"The method foo(Object[]) is ambiguous for the type X\n" + 
 			"----------\n" + 
-			"3. ERROR in X.java (at line 7)\n" + 
+			"3. ERROR in X.java (at line 8)\n" + 
 			"	new X().foo(1, new Integer(1));\n" + 
 			"	        ^^^\n" + 
 			"The method foo(Object[]) is ambiguous for the type X\n" + 
@@ -2948,6 +2957,7 @@
 				"public class X {\n" +
 				"	void foo(Number... i) { System.out.print(1); }\n" +
 				"	void foo(int... i) { System.out.print(2); }\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] args) {\n" +
 				"		new X().foo(1);\n" +
 				"		new X().foo(new Integer(1));\n" +
@@ -2956,17 +2966,17 @@
 				"}\n",
 			},
 			"----------\n" +
-			"1. ERROR in X.java (at line 5)\n" +
+			"1. ERROR in X.java (at line 6)\n" +
 			"	new X().foo(1);\n" +
 			"	        ^^^\n" +
 			"The method foo(Number[]) is ambiguous for the type X\n" +
 			"----------\n" +
-			"2. ERROR in X.java (at line 6)\n" +
+			"2. ERROR in X.java (at line 7)\n" +
 			"	new X().foo(new Integer(1));\n" +
 			"	        ^^^\n" +
 			"The method foo(Number[]) is ambiguous for the type X\n" +
 			"----------\n" +
-			"3. ERROR in X.java (at line 7)\n" +
+			"3. ERROR in X.java (at line 8)\n" +
 			"	new X().foo(1, new Integer(1));\n" +
 			"	        ^^^\n" +
 			"The method foo(Number[]) is ambiguous for the type X\n" +
@@ -2978,6 +2988,7 @@
 				"public class X {\n" +
 				"	void foo(int i, Object... o) { System.out.print(1); }\n" +
 				"	void foo(Integer o, int... i) { System.out.print(2); }\n" +
+				"	@SuppressWarnings(\"deprecation\")\n" +
 				"	public static void main(String[] args) {\n" +
 				"		new X().foo(1);\n" +
 				"		new X().foo(new Integer(1));\n" +
@@ -2986,17 +2997,17 @@
 				"}\n",
 			},
 			"----------\n" +
-			"1. ERROR in X.java (at line 5)\n" +
+			"1. ERROR in X.java (at line 6)\n" +
 			"	new X().foo(1);\n" +
 			"	        ^^^\n" +
 			"The method foo(int, Object[]) is ambiguous for the type X\n" +
 			"----------\n" +
-			"2. ERROR in X.java (at line 6)\n" +
+			"2. ERROR in X.java (at line 7)\n" +
 			"	new X().foo(new Integer(1));\n" +
 			"	        ^^^\n" +
 			"The method foo(int, Object[]) is ambiguous for the type X\n" +
 			"----------\n" +
-			"3. ERROR in X.java (at line 7)\n" +
+			"3. ERROR in X.java (at line 8)\n" +
 			"	new X().foo(1, new Integer(1));\n" +
 			"	        ^^^\n" +
 			"The method foo(int, Object[]) is ambiguous for the type X\n" +
@@ -5138,6 +5149,7 @@
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
+			"@SuppressWarnings(\"deprecation\")\n" +
 			"public class X {\n" + 
 			"    <T extends Integer> T a() { return 35; }\n" + 
 			"    <T extends Integer> T[] b() { return new int[]{35}; }\n" + 
@@ -5146,47 +5158,47 @@
 			"}\n",
 		},
 		"----------\n" + 
-		"1. WARNING in X.java (at line 2)\n" + 
+		"1. WARNING in X.java (at line 3)\n" + 
 		"	<T extends Integer> T a() { return 35; }\n" + 
 		"	           ^^^^^^^\n" + 
 		"The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended\n" + 
 		"----------\n" + 
-		"2. ERROR in X.java (at line 2)\n" + 
+		"2. ERROR in X.java (at line 3)\n" + 
 		"	<T extends Integer> T a() { return 35; }\n" + 
 		"	                                   ^^\n" + 
 		"Type mismatch: cannot convert from int to T\n" + 
 		"----------\n" + 
-		"3. WARNING in X.java (at line 3)\n" + 
+		"3. WARNING in X.java (at line 4)\n" + 
 		"	<T extends Integer> T[] b() { return new int[]{35}; }\n" + 
 		"	           ^^^^^^^\n" + 
 		"The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended\n" + 
 		"----------\n" + 
-		"4. ERROR in X.java (at line 3)\n" + 
+		"4. ERROR in X.java (at line 4)\n" + 
 		"	<T extends Integer> T[] b() { return new int[]{35}; }\n" + 
 		"	                                     ^^^^^^^^^^^^^\n" + 
 		"Type mismatch: cannot convert from int[] to T[]\n" + 
 		"----------\n" + 
-		"5. WARNING in X.java (at line 4)\n" + 
+		"5. WARNING in X.java (at line 5)\n" + 
 		"	<T extends Integer> T c() { return new Integer(35); }\n" + 
 		"	           ^^^^^^^\n" + 
 		"The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended\n" + 
 		"----------\n" + 
-		"6. ERROR in X.java (at line 4)\n" + 
+		"6. ERROR in X.java (at line 5)\n" + 
 		"	<T extends Integer> T c() { return new Integer(35); }\n" + 
 		"	                                   ^^^^^^^^^^^^^^^\n" + 
 		"Type mismatch: cannot convert from Integer to T\n" + 
 		"----------\n" + 
-		"7. WARNING in X.java (at line 5)\n" + 
+		"7. WARNING in X.java (at line 6)\n" + 
 		"	<T extends Integer> T[] d() { return new Integer[]{35}; }\n" + 
 		"	           ^^^^^^^\n" + 
 		"The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended\n" + 
 		"----------\n" + 
-		"8. ERROR in X.java (at line 5)\n" + 
+		"8. ERROR in X.java (at line 6)\n" + 
 		"	<T extends Integer> T[] d() { return new Integer[]{35}; }\n" + 
 		"	                                     ^^^^^^^^^^^^^^^^^\n" + 
 		"Type mismatch: cannot convert from Integer[] to T[]\n" + 
 		"----------\n" + 
-		"9. WARNING in X.java (at line 5)\n" + 
+		"9. WARNING in X.java (at line 6)\n" + 
 		"	<T extends Integer> T[] d() { return new Integer[]{35}; }\n" + 
 		"	                                                   ^^\n" + 
 		"The expression of type int is boxed into Integer\n" + 
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 da97cde..26e421b 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Benjamin Muskalla - Contribution for bug 239066
@@ -623,6 +627,13 @@
         "                       If multiple default encodings are specified, the last\n" + 
         "                       one will be used.\n" + 
         " \n" +
+        " Module compilation options:\n" +
+        "   These options are meaningful only in Java 9 environment or later.\n" +
+        "    --module-source-path <directories separated by " + File.pathSeparator + ">\n" +
+        "                       specify where to find source files for multiple modules\n" +
+        "    -p --module-path <directories separated by " + File.pathSeparator + ">\n" +
+        "                       specify where to find application modules\n" +
+        "    --system <jdk>      Override location of system modules \n" +
         " Compliance options:\n" +
         "    -1.3               use 1.3 compliance (-source 1.3 -target 1.1)\n" +
         "    -1.4             + use 1.4 compliance (-source 1.3 -target 1.2)\n" +
@@ -630,8 +641,9 @@
         "    -1.6 -6 -6.0       use 1.6 compliance (-source 1.6 -target 1.6)\n" +
         "    -1.7 -7 -7.0       use 1.7 compliance (-source 1.7 -target 1.7)\n" +
         "    -1.8 -8 -8.0       use 1.8 compliance (-source 1.8 -target 1.8)\n" +
-        "    -source <version>  set source level: 1.3 to 1.8 (or 5, 5.0, etc)\n" +
-        "    -target <version>  set classfile target: 1.1 to 1.8 (or 5, 5.0, etc)\n" +
+        "    -1.9 -9 -9.0       use 1.9 compliance (-source 1.9 -target 1.9)\n" +
+        "    -source <version>  set source level: 1.3 to 1.9 (or 6, 6.0, etc)\n" +
+        "    -target <version>  set classfile target: 1.1 to 1.9 (or 6, 6.0, etc)\n" +
         "                       cldc1.1 can also be used to generate the StackMap\n" +
         "                       attribute\n" +
         " \n" +
@@ -10068,6 +10080,7 @@
 		},
 		"\"" + OUTPUT_DIR +  File.separator + "Y.java\""
 		+ " -sourcepath \"" + OUTPUT_DIR + File.separator + "src2[?**/*]" + "\""
+		+ " --module-source-path \"" + OUTPUT_DIR + File.separator + "src2" + "\""
 		+ " -classpath \"" + OUTPUT_DIR + File.separator + "bin1" + "\""
 		+ " -proc:none -d \"" + OUTPUT_DIR + "\"",
 		"",
@@ -12750,13 +12763,9 @@
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=419351
 public void testBug419351() {
 	String backup = System.getProperty("java.endorsed.dirs");
-	String currentWorkingDirectoryPath = System.getProperty("user.dir");
-	if (currentWorkingDirectoryPath == null) {
-		fail("BatchCompilerTest#testBug419351 could not access the current working directory " + currentWorkingDirectoryPath);
-	} else if (!new File(currentWorkingDirectoryPath).isDirectory()) {
-		fail("BatchCompilerTest#testBug419351 current working directory is not a directory " + currentWorkingDirectoryPath);
-	}
-	String endorsedPath = currentWorkingDirectoryPath + File.separator + "endorsed";
+	if (backup == null)
+		return; // Don't bother running if it is JRE9, where there's no endorsed.dir
+	String endorsedPath = LIB_DIR + File.separator + "endorsed";
 	new File(endorsedPath).mkdir();
 	String lib1Path = endorsedPath + File.separator + "lib1.jar";
 	try {
@@ -12789,7 +12798,6 @@
 				"",
 		        true);
 	} catch (IOException e) {
-		System.err.println("BatchCompilerTest#testBug419351 could not write to current working directory " + currentWorkingDirectoryPath);
 	} finally {
 		System.setProperty("java.endorsed.dirs", backup);
 		new File(endorsedPath).delete();
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
index 4fe1df1..f2e6d70 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for 
@@ -1626,7 +1630,7 @@
 			"        public void callSite() {\n" +
 			"            // expect warning not there:\n" +
 			"            ((A) this.getAA()).callMe();\n" +
-			"            Integer max = new Integer(1);\n" +
+			"            Integer max = Integer.valueOf(1);\n" +
 			"            // execpted warning there:\n" +
 			"            Integer other = (Integer) max;\n" +
 			"        }\n" +
@@ -1923,7 +1927,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Byte((byte)1);\n" + 
+			"		return Byte.valueOf((byte)1);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -1960,7 +1964,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Character('d');\n" + 
+			"		return Character.valueOf('d');\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -1998,7 +2002,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Integer(1);\n" + 
+			"		return Integer.valueOf(1);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -2070,7 +2074,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Long(Long.MAX_VALUE);\n" + 
+			"		return Long.valueOf(Long.MAX_VALUE);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -2107,7 +2111,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Short((short) 1);\n" + 
+			"		return Short.valueOf((short) 1);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -2144,7 +2148,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Double(1.0);\n" + 
+			"		return Double.valueOf(1.0);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -2181,7 +2185,7 @@
 			"		System.out.println(y);\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Float(1.0f);\n" + 
+			"		return Float.valueOf(1.0f);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
@@ -2223,7 +2227,7 @@
 			"		System.out.println(\"FAIL\");\n" + 
 			"	}\n" + 
 			"	public static Object foo() {\n" + 
-			"		return new Float(1.0f);\n" + 
+			"		return Float.valueOf(1.0f);\n" + 
 			"	}\n" + 
 			"}";
 	if (options.sourceLevel < ClassFileConstants.JDK1_7) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index bd2c172..5da04c5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Benjamin Muskalla - Contribution for bug 239066
@@ -356,6 +360,7 @@
 		expectedProblemAttributes.put("AbstractMethodMustBeImplemented", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("AbstractMethodMustBeImplementedOverConcreteMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("AbstractMethodsInConcreteClass", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("AbstractServiceImplementation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("AmbiguousConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("AmbiguousConstructorInDefaultConstructor", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("AmbiguousConstructorInImplicitConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -396,6 +401,7 @@
 		expectedProblemAttributes.put("AssignmentToMultiCatchParameter", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("AssignmentToResource", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("AutoManagedResourceNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+		expectedProblemAttributes.put("AutoManagedVariableResourceNotBelow9", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("BinaryLiteralNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("BodyForAbstractMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("BodyForNativeMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -448,6 +454,7 @@
 		expectedProblemAttributes.put("ConflictingInheritedNullAnnotations", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("ConstructorReferenceNotBelow18", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+		expectedProblemAttributes.put("CyclicModuleDependency", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("CorruptedSignature", new ProblemAttributes(CategorizedProblem.CAT_BUILDPATH));
 		expectedProblemAttributes.put("DanglingReference", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -468,6 +475,7 @@
 		expectedProblemAttributes.put("DuplicateBoundInIntersectionCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateCase", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("DuplicateDefaultCase", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
+		expectedProblemAttributes.put("DuplicateExports", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("DuplicateFinalLocalInitialization", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("DuplicateImport", new ProblemAttributes(CategorizedProblem.CAT_IMPORT));
@@ -481,12 +489,18 @@
 		expectedProblemAttributes.put("DuplicateModifierForMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("DuplicateModifierForType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateModifierForVariable", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("DuplicateModuleRef", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateNestedType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("DuplicateOpens", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateParameterizedMethods", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("DuplicateRequires", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("DuplicateResource", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
+		expectedProblemAttributes.put("DuplicateServices", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateSuperInterface", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("DuplicateTargetInTargetAnnotation", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("DuplicateTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("DuplicateTypes", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("DuplicateUses", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("EmptyControlFlowStatement", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("EnclosingInstanceInConstructorCall", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("EndOfSource", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
@@ -514,6 +528,7 @@
 		expectedProblemAttributes.put("FieldHidingField", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
 		expectedProblemAttributes.put("FieldHidingLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
 		expectedProblemAttributes.put("FieldMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
+		expectedProblemAttributes.put("FieldMustBeFinal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("FieldTypeAmbiguous", DEPRECATED);
 		expectedProblemAttributes.put("FieldTypeInheritedNameHidesEnclosingName", DEPRECATED);
 		expectedProblemAttributes.put("FieldTypeInternalNameProvided", DEPRECATED);
@@ -554,6 +569,7 @@
 		expectedProblemAttributes.put("IllegalModifierCombinationFinalAbstractForClass", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("IllegalModifierCombinationFinalVolatileForField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("IllegalModifierCombinationForInterfaceMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("IllegalModifierCombinationForPrivateInterfaceMethod9", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("IllegalModifierForAnnotationField", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("IllegalModifierForAnnotationMemberType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("IllegalModifierForAnnotationMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -575,6 +591,8 @@
 		expectedProblemAttributes.put("IllegalModifierForMemberEnum", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("IllegalModifierForMemberInterface", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("IllegalModifierForMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("IllegalModifierForModule", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("IllegalModifierForInterfaceMethod9", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("IllegalModifierForVariable", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("IllegalModifiersForElidedType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("IllegalModifiers", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -671,9 +689,12 @@
 		expectedProblemAttributes.put("InvalidLocationForModifiers", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("InvalidNullToSynchronized", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("InvalidOctal", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+		expectedProblemAttributes.put("InvalidOpensStatement", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("InvalidOperator", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("InvalidParameterizedExceptionType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("InvalidParenthesizedExpression", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+		expectedProblemAttributes.put("InvalidServiceIntfType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("InvalidServiceImplType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("InvalidTypeExpression", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("InvalidTypeArguments", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("InvalidTypeForCollection", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -822,6 +843,7 @@
 		expectedProblemAttributes.put("NeedToEmulateFieldReadAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("NeedToEmulateFieldWriteAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("NeedToEmulateMethodAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
+		expectedProblemAttributes.put("NestedServiceImpl", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("NoAdditionalBoundAfterTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("NoFieldOnBaseType", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("NoGenericLambda", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -831,6 +853,7 @@
 		expectedProblemAttributes.put("NoSuperInInterfaceContext", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("NonBlankFinalLocalAssignment", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("NonConstantExpression", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
+		expectedProblemAttributes.put("NonDenotableTypeArgumentForAnonymousDiamond", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("NonExternalizedStringLiteral", new ProblemAttributes(CategorizedProblem.CAT_NLS));
 		expectedProblemAttributes.put("NonGenericConstructor", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("NonGenericMethod", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -883,6 +906,7 @@
 		expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
 		expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("PackageDoesNotExistOrIsEmpty", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("PackageIsNotExpectedPackage", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -916,6 +940,7 @@
 		expectedProblemAttributes.put("PotentialNullExpressionReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("PotentialNullUnboxing", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+		expectedProblemAttributes.put("ProviderMethodOrConstructorRequiredForServiceImpl", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("PublicClassMustMatchFileName", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
@@ -966,6 +991,8 @@
 		expectedProblemAttributes.put("ReturnTypeNotVisible", DEPRECATED);
 		expectedProblemAttributes.put("SafeVarargsOnFixedArityMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("SafeVarargsOnNonFinalInstanceMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("ServiceImplDefaultConstructorNotPublic", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+		expectedProblemAttributes.put("ServiceImplNotDefinedByModule", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("ShouldImplementHashcode", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("ShouldReturnValue", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("ShouldReturnValueHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -1025,6 +1052,7 @@
 		expectedProblemAttributes.put("UndefinedField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("UndefinedLabel", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("UndefinedMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("UndefinedModule", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("UndefinedName", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("UndefinedType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
 		expectedProblemAttributes.put("UndefinedTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -1200,6 +1228,7 @@
 		expectedProblemAttributes.put("AbstractMethodMustBeImplemented", SKIP);
 		expectedProblemAttributes.put("AbstractMethodMustBeImplementedOverConcreteMethod", SKIP);
 		expectedProblemAttributes.put("AbstractMethodsInConcreteClass", SKIP);
+		expectedProblemAttributes.put("AbstractServiceImplementation", SKIP);
 		expectedProblemAttributes.put("AmbiguousConstructor", SKIP);
 		expectedProblemAttributes.put("AmbiguousConstructorInDefaultConstructor", SKIP);
 		expectedProblemAttributes.put("AmbiguousConstructorInImplicitConstructorCall", SKIP);
@@ -1240,6 +1269,7 @@
 		expectedProblemAttributes.put("AssignmentToMultiCatchParameter", SKIP);
 		expectedProblemAttributes.put("AssignmentToResource", SKIP);
 		expectedProblemAttributes.put("AutoManagedResourceNotBelow17", SKIP);
+		expectedProblemAttributes.put("AutoManagedVariableResourceNotBelow9", SKIP);
 		expectedProblemAttributes.put("BinaryLiteralNotBelow17", SKIP);
 		expectedProblemAttributes.put("BodyForAbstractMethod", SKIP);
 		expectedProblemAttributes.put("BodyForNativeMethod", SKIP);
@@ -1293,6 +1323,7 @@
 		expectedProblemAttributes.put("ContradictoryNullAnnotationsInferredFunctionType", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
 		expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(JavaCore.COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST));
 		expectedProblemAttributes.put("CorruptedSignature", SKIP);
+		expectedProblemAttributes.put("CyclicModuleDependency", SKIP);
 		expectedProblemAttributes.put("DanglingReference", SKIP);
 		expectedProblemAttributes.put("DeadCode", new ProblemAttributes(JavaCore.COMPILER_PB_DEAD_CODE));
 		expectedProblemAttributes.put("DefaultMethodNotBelow18", SKIP);
@@ -1311,6 +1342,7 @@
 		expectedProblemAttributes.put("DuplicateBoundInIntersectionCast", SKIP);
 		expectedProblemAttributes.put("DuplicateCase", SKIP);
 		expectedProblemAttributes.put("DuplicateDefaultCase", SKIP);
+		expectedProblemAttributes.put("DuplicateExports", SKIP);
 		expectedProblemAttributes.put("DuplicateField", SKIP);
 		expectedProblemAttributes.put("DuplicateFinalLocalInitialization", SKIP);
 		expectedProblemAttributes.put("DuplicateImport", SKIP);
@@ -1324,12 +1356,18 @@
 		expectedProblemAttributes.put("DuplicateModifierForMethod", SKIP);
 		expectedProblemAttributes.put("DuplicateModifierForType", SKIP);
 		expectedProblemAttributes.put("DuplicateModifierForVariable", SKIP);
+		expectedProblemAttributes.put("DuplicateModuleRef", SKIP);
 		expectedProblemAttributes.put("DuplicateNestedType", SKIP);
+		expectedProblemAttributes.put("DuplicateOpens", SKIP);
 		expectedProblemAttributes.put("DuplicateParameterizedMethods", SKIP);
+		expectedProblemAttributes.put("DuplicateRequires", SKIP);
+		expectedProblemAttributes.put("DuplicateResource", SKIP);
+		expectedProblemAttributes.put("DuplicateServices", SKIP);
 		expectedProblemAttributes.put("DuplicateSuperInterface", SKIP);
 		expectedProblemAttributes.put("DuplicateTargetInTargetAnnotation", SKIP);
 		expectedProblemAttributes.put("DuplicateTypeVariable", SKIP);
 		expectedProblemAttributes.put("DuplicateTypes", SKIP);
+		expectedProblemAttributes.put("DuplicateUses", SKIP);
 		expectedProblemAttributes.put("EmptyControlFlowStatement", new ProblemAttributes(JavaCore.COMPILER_PB_EMPTY_STATEMENT));
 		expectedProblemAttributes.put("EnclosingInstanceInConstructorCall", SKIP);
 		expectedProblemAttributes.put("EndOfSource", SKIP);
@@ -1348,6 +1386,7 @@
 		expectedProblemAttributes.put("ExplicitThisParameterNotInLambda", SKIP);
 		expectedProblemAttributes.put("ExplicitThisParameterNotBelow18", SKIP);
 		expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE));
+		expectedProblemAttributes.put("ExportedPackageDoesNotExistOrIsEmpty", SKIP);
 		expectedProblemAttributes.put("ExpressionShouldBeAVariable", SKIP);
 		expectedProblemAttributes.put("ExternalProblemFixable", SKIP);
 		expectedProblemAttributes.put("ExternalProblemNotFixable", SKIP);
@@ -1357,6 +1396,7 @@
 		expectedProblemAttributes.put("FieldHidingField", new ProblemAttributes(JavaCore.COMPILER_PB_FIELD_HIDING));
 		expectedProblemAttributes.put("FieldHidingLocalVariable", new ProblemAttributes(JavaCore.COMPILER_PB_FIELD_HIDING));
 		expectedProblemAttributes.put("FieldMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION));
+		expectedProblemAttributes.put("FieldMustBeFinal", SKIP);
 		expectedProblemAttributes.put("FieldTypeAmbiguous", SKIP);
 		expectedProblemAttributes.put("FieldTypeInheritedNameHidesEnclosingName", SKIP);
 		expectedProblemAttributes.put("FieldTypeInternalNameProvided", SKIP);
@@ -1397,6 +1437,7 @@
 		expectedProblemAttributes.put("IllegalModifierCombinationFinalAbstractForClass", SKIP);
 		expectedProblemAttributes.put("IllegalModifierCombinationFinalVolatileForField", SKIP);
 		expectedProblemAttributes.put("IllegalModifierCombinationForInterfaceMethod", SKIP);
+		expectedProblemAttributes.put("IllegalModifierCombinationForPrivateInterfaceMethod9", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForAnnotationField", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForAnnotationMemberType", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForAnnotationMethod", SKIP);
@@ -1418,6 +1459,8 @@
 		expectedProblemAttributes.put("IllegalModifierForMemberEnum", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForMemberInterface", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForMethod", SKIP);
+		expectedProblemAttributes.put("IllegalModifierForModule", SKIP);
+		expectedProblemAttributes.put("IllegalModifierForInterfaceMethod9", SKIP);
 		expectedProblemAttributes.put("IllegalModifierForVariable", SKIP);
 		expectedProblemAttributes.put("IllegalModifiersForElidedType", SKIP);
 		expectedProblemAttributes.put("IllegalModifiers", SKIP);
@@ -1513,9 +1556,12 @@
 		expectedProblemAttributes.put("InvalidLocationForModifiers", SKIP);
 		expectedProblemAttributes.put("InvalidNullToSynchronized", SKIP);
 		expectedProblemAttributes.put("InvalidOctal", SKIP);
+		expectedProblemAttributes.put("InvalidOpensStatement", SKIP);
 		expectedProblemAttributes.put("InvalidOperator", SKIP);
 		expectedProblemAttributes.put("InvalidParameterizedExceptionType", SKIP);
 		expectedProblemAttributes.put("InvalidParenthesizedExpression", SKIP);
+		expectedProblemAttributes.put("InvalidServiceIntfType", SKIP);
+		expectedProblemAttributes.put("InvalidServiceImplType", SKIP);
 		expectedProblemAttributes.put("InvalidTypeArguments", SKIP);
 		expectedProblemAttributes.put("InvalidTypeExpression", SKIP);
 		expectedProblemAttributes.put("InvalidTypeForCollection", SKIP);
@@ -1665,6 +1711,7 @@
 		expectedProblemAttributes.put("NeedToEmulateFieldReadAccess", new ProblemAttributes(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION));
 		expectedProblemAttributes.put("NeedToEmulateFieldWriteAccess", new ProblemAttributes(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION));
 		expectedProblemAttributes.put("NeedToEmulateMethodAccess", new ProblemAttributes(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION));
+		expectedProblemAttributes.put("NestedServiceImpl", SKIP);
 		expectedProblemAttributes.put("NoAdditionalBoundAfterTypeVariable", SKIP);
 		expectedProblemAttributes.put("NoFieldOnBaseType", SKIP);
 		expectedProblemAttributes.put("NoGenericLambda", SKIP);
@@ -1674,6 +1721,7 @@
 		expectedProblemAttributes.put("NoSuperInInterfaceContext", SKIP);
 		expectedProblemAttributes.put("NonBlankFinalLocalAssignment", SKIP);
 		expectedProblemAttributes.put("NonConstantExpression", SKIP);
+		expectedProblemAttributes.put("NonDenotableTypeArgumentForAnonymousDiamond", SKIP);
 		expectedProblemAttributes.put("NonExternalizedStringLiteral", new ProblemAttributes(JavaCore.COMPILER_PB_NON_NLS_STRING_LITERAL));
 		expectedProblemAttributes.put("NonGenericConstructor", SKIP);
 		expectedProblemAttributes.put("NonGenericMethod", SKIP);
@@ -1726,6 +1774,7 @@
 		expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION));
 		expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD));
 		expectedProblemAttributes.put("PackageCollidesWithType", SKIP);
+		expectedProblemAttributes.put("PackageDoesNotExistOrIsEmpty", SKIP);
 		expectedProblemAttributes.put("PackageIsNotExpectedPackage", SKIP);
 		expectedProblemAttributes.put("ParameterAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_PARAMETER_ASSIGNMENT));
 		expectedProblemAttributes.put("ParameterLackingNonNullAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_PARAMETER_ANNOTATION_DROPPED));
@@ -1759,6 +1808,7 @@
 		expectedProblemAttributes.put("PotentialNullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
 		expectedProblemAttributes.put("PotentialNullUnboxing", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
 		expectedProblemAttributes.put("PotentialNullMessageSendReference", new ProblemAttributes(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE));
+		expectedProblemAttributes.put("ProviderMethodOrConstructorRequiredForServiceImpl", SKIP);
 		expectedProblemAttributes.put("PublicClassMustMatchFileName", SKIP);
 		expectedProblemAttributes.put("RawMemberTypeCannotBeParameterized", SKIP);
 		expectedProblemAttributes.put("RawTypeReference", new ProblemAttributes(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE));
@@ -1809,6 +1859,8 @@
 		expectedProblemAttributes.put("ReturnTypeNotVisible", SKIP);
 		expectedProblemAttributes.put("SafeVarargsOnFixedArityMethod", SKIP);
 		expectedProblemAttributes.put("SafeVarargsOnNonFinalInstanceMethod", SKIP);
+		expectedProblemAttributes.put("ServiceImplDefaultConstructorNotPublic", SKIP);
+		expectedProblemAttributes.put("ServiceImplNotDefinedByModule", SKIP);
 		expectedProblemAttributes.put("ShouldImplementHashcode", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_HASHCODE_METHOD));
 		expectedProblemAttributes.put("ShouldReturnValue", SKIP);
 		expectedProblemAttributes.put("ShouldReturnValueHintMissingDefault", SKIP);
@@ -1868,6 +1920,7 @@
 		expectedProblemAttributes.put("UndefinedField", SKIP);
 		expectedProblemAttributes.put("UndefinedLabel", SKIP);
 		expectedProblemAttributes.put("UndefinedMethod", SKIP);
+		expectedProblemAttributes.put("UndefinedModule", SKIP);
 		expectedProblemAttributes.put("UndefinedName", SKIP);
 		expectedProblemAttributes.put("UndefinedType", SKIP);
 		expectedProblemAttributes.put("UndefinedTypeVariable", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_3.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_3.java
index 2bbc342..5316668 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_3.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_3.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -2825,10 +2829,10 @@
 			"import java.lang.reflect.*;\n" +
 			"public class X extends Date implements Runnable{\n" +
 			" \n" +
-			" Integer w = new Integer(90);\n" +
+			" Integer w = Integer.valueOf(90);\n" +
 			" protected double x = 91.1;\n" +
 			" public long y = 92;\n" +
-			" static public Boolean z = new Boolean(true); \n" +
+			" static public Boolean z = Boolean.valueOf(true); \n" +
 			" public class X_inner {\n" +
 			"  public X_inner() {\n" +
 			"   this.super();\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
index 3d99dd3..19437f9 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contribution for bug 185682 - Increment/decrement operators mark local variables as read
@@ -2857,10 +2861,10 @@
 			"import java.lang.reflect.*;\n" +
 			"public class X extends Date implements Runnable{\n" +
 			" \n" +
-			" Integer w = new Integer(90);\n" +
+			" Integer w = Integer.valueOf(90);\n" +
 			" protected double x = 91.1;\n" +
 			" public long y = 92;\n" +
-			" static public Boolean z = new Boolean(true); \n" +
+			" static public Boolean z = Boolean.valueOf(true); \n" +
 			" public class X_inner {\n" +
 			"  public X_inner() {\n" +
 			"   this.super();\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
index 384bc1a..30e90c6 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -2968,7 +2972,7 @@
 		"Type null of the last argument to method getMethod(String, Class...) doesn't exactly match the vararg parameter type. Cast to Class[] to confirm the non-varargs invocation, or pass individual arguments of type Class for a varargs invocation.\n" +
 		"----------\n";
 	String javaVersion = System.getProperty("java.version");
-	if (isJRELevel(AbstractCompilerTest.F_1_6|AbstractCompilerTest.F_1_7|AbstractCompilerTest.F_1_8)
+	if (isJRELevel(AbstractCompilerTest.F_1_6|AbstractCompilerTest.F_1_7|AbstractCompilerTest.F_1_8|AbstractCompilerTest.F_9)
 			|| (AbstractCompilerTest.getPossibleComplianceLevels() == AbstractCompilerTest.F_1_5
 				&& javaVersion.indexOf("1.5") == -1)) {
 		errorMessage =
@@ -3002,10 +3006,10 @@
 			"import java.lang.reflect.*;\n" +
 			"public class X extends Date implements Runnable{\n" +
 			" \n" +
-			" Integer w = new Integer(90);\n" +
+			" Integer w = Integer.valueOf(90);\n" +
 			" protected double x = 91.1;\n" +
 			" public long y = 92;\n" +
-			" static public Boolean z = new Boolean(true); \n" +
+			" static public Boolean z = Boolean.valueOf(true); \n" +
 			" public class X_inner {\n" +
 			"  public X_inner() {\n" +
 			"   this.super();\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConditionalExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConditionalExpressionTest.java
index 3ee6ed5..526476b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConditionalExpressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConditionalExpressionTest.java
@@ -1,16 +1,23 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
+import java.util.Map;
+
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
 import junit.framework.Test;
 
@@ -518,6 +525,8 @@
 	public void test427625() {
 		if (this.complianceLevel < ClassFileConstants.JDK1_5)
 			return;
+		Map<String,String> options = getCompilerOptions();
+		options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 		this.runNegativeTest(
 				new String[] {
 						"X.java",
@@ -536,7 +545,8 @@
 						"	}\n" +
 						"}\n",
 				},
-				"");
+				"",
+				null, true, options);
 	}	
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=432487,  NullPointerException during compilation using jdk1.8.0
 	public void testBug432487() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
index a75ae52..5f12199 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnclosingMethodAttributeTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index 236bae0..68d3f69 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -5,7 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
- * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -6583,7 +6586,7 @@
 				"public class X {\n" +
 				"	void foo() {\n" +
 				"		ArrayList<? super Integer> al = new ArrayList<Object>();\n" +
-				"		al.add(new Integer(1)); // (1)\n" +
+				"		al.add(Integer.valueOf(1)); // (1)\n" +
 				"		Integer i = al.get(0);  // (2)\n" +
 				"	}\n" +
 				"}\n",
@@ -6605,13 +6608,13 @@
 				"public class X {\n" +
 				"	void foo() {\n" +
 				"		ArrayList<? extends Integer> al = new ArrayList<Integer>();\n" +
-				"		al.add(new Integer(1)); // (1)\n" +
+				"		al.add(Integer.valueOf(1)); // (1)\n" +
 				"	}\n" +
 				"}\n",
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 6)\n" +
-			"	al.add(new Integer(1)); // (1)\n" +
+			"	al.add(Integer.valueOf(1)); // (1)\n" +
 			"	   ^^^\n" +
 			"The method add(capture#1-of ? extends Integer) in the type ArrayList<capture#1-of ? extends Integer> is not applicable for the arguments (Integer)\n" +
 			"----------\n");
@@ -6624,7 +6627,7 @@
 				"public class X {\n" +
 				"	public static void main(String[] args) {\n" +
 				"		XList<? super Integer> lx = new XList<Integer>();\n" +
-				"		lx.slot = new Integer(1);\n" +
+				"		lx.slot = Integer.valueOf(1);\n" +
 				"		Integer i = lx.slot;\n" +
 				"    }    	\n" +
 				"}\n" +
@@ -7279,13 +7282,15 @@
 	}
 	// 69776 - variation
 	public void test0242() {
+		Map<String,String> options = getCompilerOptions();
+		options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
 				"import java.util.HashMap;\n" +
 				"import java.util.Map;\n" +
+				"@SuppressWarnings({\"rawtypes\"})\n" +
 				"public class X {\n" +
-				"    @SuppressWarnings(\"rawtypes\")\n" +
 				"    private static final Map<String, Class> classes = new HashMap<String, Class>();\n" +
 				"    public static void main(String[] args) throws Exception {\n" +
 				"    	classes.put(\"test\", X.class);\n" +
@@ -7326,7 +7331,8 @@
 			"	final Class<String> clazz3 = (Class<String>) classes.get(\"test\");\n" +
 			"	                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Unnecessary cast from Class to Class<String>\n" +
-			"----------\n");
+			"----------\n", 
+			null, true, options );
 	}
 	public void test0243() {
 		this.runConformTest(
@@ -7692,6 +7698,7 @@
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
+				"@SuppressWarnings(\"deprecation\")\n" +
 				"public class X { \n" +
 				"    static class A {\n" +
 				"    }\n" +
@@ -7702,7 +7709,7 @@
 				"}\n"
 			},
 			"----------\n" +
-			"1. ERROR in X.java (at line 6)\n" +
+			"1. ERROR in X.java (at line 7)\n" +
 			"	return clazz.newInstance(); // ? extends Object\n" +
 			"	       ^^^^^^^^^^^^^^^^^^^\n" +
 			"Type mismatch: cannot convert from capture#1-of ? extends Object to X.A\n" +
@@ -7750,7 +7757,7 @@
 				"        List<Integer> li= new ArrayList<Integer>();\n" +
 				"        List<? extends Number> ls= li;       \n" +
 				"        List<Number> x2= (List<Number>)ls;//unsafe\n" +
-				"        x2.add(new Float(1.0));\n" +
+				"        x2.add(Float.valueOf(1.0f));\n" +
 				"        \n" +
 				"        Integer i= li.get(0);//ClassCastException!\n" +
 				"        \n" +
@@ -12935,7 +12942,7 @@
 				"		A<Long> a = new A<Long>() {\n" +
 				"			@Override\n" +
 				"			Long get() {\n" +
-				"				return new Long(5);\n" +
+				"				return Long.valueOf(5);\n" +
 				"			}\n" +
 				"		};\n" +
 				"	}\n" +
@@ -13271,21 +13278,21 @@
 				"    }\n" +
 				"\n" +
 				"    public void test01() { // works\n" +
-				"        new IntegerOrder().next(new Integer(0)); // works\n" +
+				"        new IntegerOrder().next(Integer.valueOf(0)); // works\n" +
 				"    }\n" +
 				"\n" +
 				"    public void test02() { // doesn\'t work\n" +
 				"        final DiscreteOrder<Integer> order = new IntegerOrder();\n" +
-				"        order.next(new Integer(0));\n" +
+				"        order.next(Integer.valueOf(0));\n" +
 				"    }\n" +
 				"\n" +
 				"    public void test03() { // works\n" +
-				"        new IntegerOrder2().next(new Integer(0)); // works\n" +
+				"        new IntegerOrder2().next(Integer.valueOf(0)); // works\n" +
 				"    }\n" +
 				"\n" +
 				"    public void test04() { // doesn\'t work\n" +
 				"        final DiscreteOrder<Integer> order = new IntegerOrder2();\n" +
-				"        order.next(new Integer(0));\n" +
+				"        order.next(Integer.valueOf(0));\n" +
 				"    }\n" +
 				"}\n",
 				"orders/DiscreteOrder.java",//===============================
@@ -13313,11 +13320,11 @@
 				"    }\n" +
 				"\n" +
 				"    public Integer previous(Integer arg0) {\n" +
-				"        return new Integer(arg0.intValue() - 1);\n" +
+				"        return Integer.valueOf(arg0.intValue() - 1);\n" +
 				"    }\n" +
 				"\n" +
 				"    public Integer next(Integer arg0) {\n" +
-				"        return new Integer(arg0.intValue() + 1);\n" +
+				"        return Integer.valueOf(arg0.intValue() + 1);\n" +
 				"    }\n" +
 				"}\n",
 				"orders/impl/IntegerOrder2.java",//===============================
@@ -14098,7 +14105,7 @@
 				"  \n" +
 				"  public ITest<C> get()\n" +
 				"  {\n" +
-				"    return m_manager.getById(getClass(), new Integer(1));\n" +
+				"    return m_manager.getById(getClass(), Integer.valueOf(1));\n" +
 				"  }\n" +
 				"    \n" +
 				"  public static class Manager<C extends X>\n" +
@@ -14117,13 +14124,13 @@
 			"Zork cannot be resolved to a type\n" + 
 			"----------\n" + 
 			"2. WARNING in X.java (at line 16)\n" + 
-			"	return m_manager.getById(getClass(), new Integer(1));\n" + 
-			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"	return m_manager.getById(getClass(), Integer.valueOf(1));\n" + 
+			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Type safety: Unchecked invocation getById(Class<capture#1-of ? extends Test>, Integer) of the generic method getById(Class<T>, Integer) of type Test.Manager<C>\n" + 
 			"----------\n" + 
 			"3. WARNING in X.java (at line 16)\n" + 
-			"	return m_manager.getById(getClass(), new Integer(1));\n" + 
-			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"	return m_manager.getById(getClass(), Integer.valueOf(1));\n" + 
+			"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Type safety: The expression of type Test needs unchecked conversion to conform to ITest<C>\n" + 
 			"----------\n");
 	}
@@ -14420,33 +14427,33 @@
 				"	}\n" +
 				"\n" +
 				"	public static void foo() {\n" +
-				"		Comparable s1 = choose(true, \"string\", new Integer(1));\n" +
-				"		Number s2 = choose(true, new Integer(1), new Float(2));\n" +
-				"		Comparable s3 = choose(true, new Integer(1), new Float(2));\n" +
-				"		Cloneable s4 = choose(true, new Integer(1), new Float(2));\n" +
-				"		Cloneable s5 = choose(true, \"string\", new Integer(1));\n" +
+				"		Comparable s1 = choose(true, \"string\", Integer.valueOf(1));\n" +
+				"		Number s2 = choose(true, Integer.valueOf(1), Float.valueOf(2));\n" +
+				"		Comparable s3 = choose(true, Integer.valueOf(1), Float.valueOf(2));\n" +
+				"		Cloneable s4 = choose(true, Integer.valueOf(1), Float.valueOf(2));\n" +
+				"		Cloneable s5 = choose(true, \"string\", Integer.valueOf(1));\n" +
 				"	}\n" +
 				"}\n"
 			},
 			"----------\n" +
 			"1. WARNING in X.java (at line 9)\n" +
-			"	Comparable s1 = choose(true, \"string\", new Integer(1));\n" +
+			"	Comparable s1 = choose(true, \"string\", Integer.valueOf(1));\n" +
 			"	^^^^^^^^^^\n" +
 			"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" +
 			"----------\n" +
 			"2. WARNING in X.java (at line 11)\n" +
-			"	Comparable s3 = choose(true, new Integer(1), new Float(2));\n" +
+			"	Comparable s3 = choose(true, Integer.valueOf(1), Float.valueOf(2));\n" +
 			"	^^^^^^^^^^\n" +
 			"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 12)\n" +
-			"	Cloneable s4 = choose(true, new Integer(1), new Float(2));\n" +
-			"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"	Cloneable s4 = choose(true, Integer.valueOf(1), Float.valueOf(2));\n" +
+			"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Type mismatch: cannot convert from Number&Comparable<?> to Cloneable\n" +
 			"----------\n" +
 			"4. ERROR in X.java (at line 13)\n" +
-			"	Cloneable s5 = choose(true, \"string\", new Integer(1));\n" +
-			"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"	Cloneable s5 = choose(true, \"string\", Integer.valueOf(1));\n" +
+			"	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Type mismatch: cannot convert from Object&Serializable&Comparable<?> to Cloneable\n" +
 			"----------\n");
 	}
@@ -14620,7 +14627,7 @@
 				"public class X {\n" +
 				"    void method(List<? super Number> list) {\n" +
 				"        list.add(new Object());   // should fail\n" +
-				"        list.add(new Integer(3)); // correct\n" +
+				"        list.add(Integer.valueOf(3)); // correct\n" +
 				"    }\n" +
 				"}\n"
 			},
@@ -17941,7 +17948,7 @@
 				"\n" +
 				"class Bar implements IFoo<Integer> {\n" +
 				"    public Integer get(Class<Integer> arg0) {\n" +
-				"        return new Integer(3);\n" +
+				"        return Integer.valueOf(3);\n" +
 				"    }\n" +
 				"}\n" +
 				"}\n",
@@ -20923,7 +20930,7 @@
 			"	}\n" +
 			"\n" +
 			"	public static void main(String[] arg) throws Exception {\n" +
-			"		X<String, Integer> ref = new X<String, Integer>(\"Dummy Key\", new Integer(5), queue);\n" +
+			"		X<String, Integer> ref = new X<String, Integer>(\"Dummy Key\", Integer.valueOf(5), queue);\n" +
 			"		new Thread() {\n" +
 			"			@Override\n" +
 			"			public void run() {\n" +
@@ -39411,7 +39418,7 @@
 			"\n" +
 			"	public List<Integer> getList() {\n" +
 			"		ArrayList<Integer> l = new ArrayList<Integer>();\n" +
-			"		l.add(new Integer(0));\n" +
+			"		l.add(Integer.valueOf(0));\n" +
 			"		return l;\n" +
 			"	}\n" +
 			"\n" +
@@ -51241,6 +51248,7 @@
 	this.runNegativeTest(
 			new String[] {
 					"CompilerBug.java",
+					"@SuppressWarnings(\"deprecation\")\n" +
 					"public class CompilerBug {\n" +
 					"	public <T> T newInstance( Class<T> c ) throws InstantiationException, IllegalAccessException {\n" +
 					"	      return c.newInstance();\n" +
@@ -51268,7 +51276,7 @@
 			},
 			this.complianceLevel <= ClassFileConstants.JDK1_6 ?
 			"----------\n" + 
-			"1. ERROR in CompilerBug.java (at line 22)\n" + 
+			"1. ERROR in CompilerBug.java (at line 23)\n" + 
 			"	Zork z;\n" + 
 			"	^^^^\n" + 
 			"Zork cannot be resolved to a type\n" + 
@@ -51276,17 +51284,17 @@
 				
 			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622
 			"----------\n" + 
-			"1. ERROR in CompilerBug.java (at line 17)\n" + 
+			"1. ERROR in CompilerBug.java (at line 18)\n" + 
 			"	getClass().newInstance().privateMethod();\n" + 
 			"	                         ^^^^^^^^^^^^^\n" + 
 			"The method privateMethod() from the type CompilerBug is not visible\n" + 
 			"----------\n" + 
-			"2. ERROR in CompilerBug.java (at line 19)\n" + 
+			"2. ERROR in CompilerBug.java (at line 20)\n" + 
 			"	getClass().newInstance().privateInt = 10;\n" + 
 			"	                         ^^^^^^^^^^\n" + 
 			"The field CompilerBug.privateInt is not visible\n" + 
 			"----------\n" + 
-			"3. ERROR in CompilerBug.java (at line 22)\n" + 
+			"3. ERROR in CompilerBug.java (at line 23)\n" + 
 			"	Zork z;\n" + 
 			"	^^^^\n" + 
 			"Zork cannot be resolved to a type\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index 8b529c0..1a014e7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -2059,6 +2063,21 @@
 		"----------\n");
 }
 public void test339478o() {
+	String log_18 = 
+			"----------\n" + 
+			"1. ERROR in X.java (at line 3)\n" + 
+			"	new X<>(){\n" + 
+			"	    ^\n" + 
+			"\'<>\' cannot be used with anonymous classes\n" + 
+			"----------\n";
+	String log_9 = 
+			"----------\n" + 
+			"1. ERROR in X.java (at line 4)\n" + 
+			"	void newMethod(){\n" + 
+			"	     ^^^^^^^^^^^\n" + 
+			"The method newMethod() of type new X<Object>(){} must override or implement a supertype method\n" + 
+			"----------\n";
+	String errorMsg = this.complianceLevel < ClassFileConstants.JDK9 ? log_18 : log_9;
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
@@ -2086,14 +2105,42 @@
 		"	    ^\n" + 
 		"\'<>\' cannot be used with anonymous classes\n" + 
 		"----------\n":
-			"----------\n" + 
-			"1. ERROR in X.java (at line 3)\n" + 
-			"	new X<>(){\n" + 
-			"	    ^\n" + 
-			"\'<>\' cannot be used with anonymous classes\n" + 
-			"----------\n");
+			errorMsg);
 }
 public void test339478p() {
+	String log_18 = 
+			"----------\n" + 
+			"1. WARNING in X.java (at line 3)\n" + 
+			"	X Test = new X<>(){\n" + 
+			"	^\n" + 
+			"X is a raw type. References to generic type X<T> should be parameterized\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 3)\n" + 
+			"	X Test = new X<>(){\n" + 
+			"	             ^\n" + 
+			"\'<>\' cannot be used with anonymous classes\n" + 
+			"----------\n";
+	String log_9 = 
+			"----------\n" + 
+			"1. WARNING in X.java (at line 3)\n" + 
+			"	X Test = new X<>(){\n" + 
+			"	^\n" + 
+			"X is a raw type. References to generic type X<T> should be parameterized\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 3)\n" + 
+			"	X Test = new X<>(){\n" + 
+			"			void newMethod(){\n" + 
+			"			}\n" + 
+			"		}.testFunction(\"SUCCESS\");\n" + 
+			"	         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+			"Type mismatch: cannot convert from void to X\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 4)\n" + 
+			"	void newMethod(){\n" + 
+			"	     ^^^^^^^^^^^\n" + 
+			"The method newMethod() of type new X<Object>(){} must override or implement a supertype method\n" + 
+			"----------\n";
+	String errorMsg = this.complianceLevel < ClassFileConstants.JDK9 ? log_18 : log_9;
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
@@ -2126,17 +2173,7 @@
 		"	             ^\n" + 
 		"\'<>\' cannot be used with anonymous classes\n" + 
 		"----------\n" : 
-			"----------\n" + 
-			"1. WARNING in X.java (at line 3)\n" + 
-			"	X Test = new X<>(){\n" + 
-			"	^\n" + 
-			"X is a raw type. References to generic type X<T> should be parameterized\n" + 
-			"----------\n" + 
-			"2. ERROR in X.java (at line 3)\n" + 
-			"	X Test = new X<>(){\n" + 
-			"	             ^\n" + 
-			"\'<>\' cannot be used with anonymous classes\n" + 
-			"----------\n");
+			errorMsg);
 }
 public void test339478q() {
 	this.runNegativeTest(
@@ -5470,6 +5507,8 @@
 		"----------\n");
 }
 public void testBug454644() {
+	Map<String,String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runNegativeTest(
 		new String[] {
 			"example/CollectionFactory.java",
@@ -5614,8 +5653,8 @@
 		"	return (Collection<E>) collectionClass.newInstance();\n" + 
 		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 		"Type safety: Unchecked cast from capture#13-of ? to Collection<E>\n" + 
-		"----------\n"
-		);
+		"----------\n",
+		null, true, options);
 }
 // original test case, documenting existing compiler behavior
 public void testBug456459a() {
@@ -5992,6 +6031,7 @@
 			"            return list;\n" + 
 			"        }\n" + 
 			"    \n" + 
+			" @SuppressWarnings(\"deprecation\")\n" +
 			"        static final <L extends List<?>> L newList(Class<L> type) {\n" + 
 			"            try {\n" + 
 			"                return type.newInstance();\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
index 805dd10..a9b7211 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
@@ -513,12 +513,19 @@
 			"	}\n" +
 			"}",
 		},
+		this.complianceLevel < ClassFileConstants.JDK9 ?
 		"----------\n" + 
 		"1. ERROR in X.java (at line 5)\n" + 
 		"	new X<>().new X2<>(){\n" + 
 		"	              ^^\n" + 
 		"\'<>\' cannot be used with anonymous classes\n" + 
-		"----------\n");
+		"----------\n":
+			"----------\n" + 
+			"1. ERROR in X.java (at line 6)\n" + 
+			"	void newMethod(){\n" + 
+			"	     ^^^^^^^^^^^\n" + 
+			"The method newMethod() of type new X<Object>.X2<Object>(){} must override or implement a supertype method\n" + 
+			"----------\n");
 }
 public void test004c() {
 	this.runConformTest(
@@ -1219,8 +1226,7 @@
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=345239
 public void test0028() {
-	this.runNegativeTest(
-		new String[] {
+	String[] testFiles = new String[] {
 			"X.java",
 			"public class X<T> {\n" +
 			"     X<String> x = new X<> () {}\n;" +
@@ -1228,18 +1234,24 @@
 			"	  }\n" +
 			"     X<String>.Y<String> y = x.new Y<>() {};\n" +
 			"}\n"
-		},
-		"----------\n" + 
-		"1. ERROR in X.java (at line 2)\n" + 
-		"	X<String> x = new X<> () {}\n" + 
-		"	                  ^\n" + 
-		"\'<>\' cannot be used with anonymous classes\n" + 
-		"----------\n" + 
-		"2. ERROR in X.java (at line 5)\n" + 
-		"	X<String>.Y<String> y = x.new Y<>() {};\n" + 
-		"	                              ^\n" + 
-		"\'<>\' cannot be used with anonymous classes\n" + 
-		"----------\n");
+		};
+	if (this.complianceLevel < ClassFileConstants.JDK9) {
+		this.runNegativeTest(
+			testFiles,
+			"----------\n" + 
+			"1. ERROR in X.java (at line 2)\n" + 
+			"	X<String> x = new X<> () {}\n" + 
+			"	                  ^\n" + 
+			"\'<>\' cannot be used with anonymous classes\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 5)\n" + 
+			"	X<String>.Y<String> y = x.new Y<>() {};\n" + 
+			"	                              ^\n" + 
+			"\'<>\' cannot be used with anonymous classes\n" + 
+			"----------\n");
+	} else {
+		this.runConformTest(testFiles);
+	}
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359
 public void test0029() {
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 d5985f1..c7f0347 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
@@ -7309,6 +7309,40 @@
 			"}\n"
 		});
 }
+
+// Redundant type argument specification error for anonymous types should not occur below source level 9 
+public void testBug488663() {
+	Map<String, String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, CompilerOptions.ERROR);
+	String[] testFiles = new String[] {
+			"C.java",
+			"import java.util.Comparator;\n" + 
+			"public class C {\n" + 
+			"	Comparator<String> comparator = new Comparator<String>() { //\n" + 
+			"		@Override\n" + 
+			"		public int compare(String o1, String o2) {\n" + 
+			"			return 0;\n" + 
+			"		}\n" + 
+			"	};\n" + 
+			"}"
+		};
+	if (this.complianceLevel < ClassFileConstants.JDK9) {
+	this.runConformTest(
+		testFiles,
+		"", options);
+	} else {
+		this.runNegativeTest(
+			testFiles, 
+			"----------\n" + 
+			"1. ERROR in C.java (at line 3)\n" + 
+			"	Comparator<String> comparator = new Comparator<String>() { //\n" + 
+			"	                                    ^^^^^^^^^^\n" + 
+			"Redundant specification of type arguments <String>\n" + 
+			"----------\n",
+			null, true, options);
+	}
+}
+
 public void testBug499725a() {
 	runConformTest(
 		new String[] {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java
new file mode 100644
index 0000000..6e4e1c4
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.Map;
+
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+import junit.framework.Test;
+
+@SuppressWarnings({ "rawtypes" })
+public class GenericsRegressionTest_9 extends AbstractRegressionTest {
+
+static {
+//	TESTS_NAMES = new String[] { "testBug488663_006" };
+//	TESTS_NUMBERS = new int[] { 40, 41, 43, 45, 63, 64 };
+//	TESTS_RANGE = new int[] { 11, -1 };
+}
+public GenericsRegressionTest_9(String name) {
+	super(name);
+}
+public static Test suite() {
+	return buildMinimalComplianceTestSuite(testClass(), F_9);
+}
+
+// vanilla test case
+public void testBug488663_001() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"	public Y<String> bar() {\n" +
+			"		Y<String> y = new Y<>() {\n" +
+			"			@Override\n" +
+			"			public void foo(String s) {\n" +
+			"				this.s = s;\n" +
+			"	 		}\n" +
+			"		};\n" +
+			"		return y;\n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		Y<String> y = new X().bar();\n" +
+			"		y.foo(\"Done\");\n" +
+			"		y.print();\n" +
+			"	}\n" +
+			"}\n" +
+			"abstract class Y<T> {\n" +
+			"	String s;\n" +
+			"	public abstract void foo(String s);\n" +
+			"	public void print() {\n" +
+			"		System.out.println(this.s);\n" +
+			"	}\n" +
+			"}\n",
+		},
+		"Done");
+}
+
+// negative test case for diamond operator instantiation of denotable anonymous type but with parameterized method
+public void testBug488663_002() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" +
+			"	public Y<String> bar() {\n" +
+			"		Y<String> y = new Y<>() {\n" +
+			"			@Override\n" +
+			"			public void foo(T t) {\n" +
+			"				this.s = t;\n" +
+			"			}\n" +
+			"		};\n" +
+			"		return y;\n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		Y<String> y = new X().bar();\n" +
+			"		y.foo(\"Done\");\n" +
+			"		y.print();\n" +
+			"	}\n" +
+			"}\n" +
+			"abstract class Y<T> {\n" +
+			"	T s;\n" +
+			"	public abstract void foo(T t);\n" +
+			"	public void print() {\n" +
+			"		System.out.println(this.s);\n" +
+			"	}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 3)\n" + 
+		"	Y<String> y = new Y<>() {\n" + 
+		"	                  ^^^^^\n" + 
+		"The type new Y<String>(){} must implement the inherited abstract method Y<String>.foo(String)\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 5)\n" + 
+		"	public void foo(T t) {\n" + 
+		"	                ^\n" + 
+		"T cannot be resolved to a type\n" + 
+		"----------\n");
+}
+
+// diamond operator instantiation of denotable anonymous types with different type params
+public void testBug488663_003() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {	\n" +
+			"@SuppressWarnings(\"unused\") \n" +
+			"	public static void main(String[] args) {\n" +
+			"		Y<?> y1 = new Y<>(){};\n" +
+			"		Y<String> y2 = new Y<>(){};\n" +
+			"		Y<? extends String> y3 = new Y<>() {};\n" +
+			"		Y<? super String> y4 = new Y<>() {};\n" +
+			"	}\n" +
+			"}\n" +
+			"class Y<T> {}\n",
+		},
+		"");
+}
+
+// inner classes with diamond operator and anonymous classes
+public void testBug488663_004() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {	\n" +
+			"@SuppressWarnings(\"unused\") \n" +
+			"	public static void main(String[] args) {\n" +
+			"		Y<?> y1 = new X().new Y<>(){};\n" +
+			"		Y<String> y2 = new X().new Y<>(){};\n" +
+			"		Y<? extends String> y3 = new X().new Y<>() {};\n" +
+			"		Y<? super String> y4 = new X().new Y<>() {};\n" +
+			"	}\n" +
+			"\n" +
+			"	class Y<T> {}\n" +
+			"}\n",
+		},
+		"");
+}
+
+// compiler error for non-denotable anonymous type with diamond operator - negative test
+public void testBug488663_005() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"interface I {}\n" +
+				"interface J{}\n" +
+				"class Y<T extends I & J> {}\n" +
+				"\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		Y<?> y = new Y<>() {};\n" +
+				"	}\n" +
+				"}\n",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 7)\n" + 
+			"	Y<?> y = new Y<>() {};\n" + 
+			"	             ^\n" + 
+			"Type Y<I & J> inferred for Y<>, is not valid for an anonymous class with '<>'\n" + 
+			"----------\n");
+	
+}
+
+//compiler error for non-denotable anonymous type with diamond operator - negative test
+public void testBug488663_006() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"class Y<T> {\n" +
+				"   Y(T x) {}\n" +
+				"}\n" +
+				"\n" +
+				"class X {\n" +
+				"  public static void main(String[] args) {\n" +
+				"	  Y<? extends Integer> fi = null;\n" +
+				"	  Y<?> f = new Y<>(fi){};\n" +
+				"  }\n" +
+				"}\n",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 8)\n" + 
+			"	Y<?> f = new Y<>(fi){};\n" + 
+			"	             ^\n" + 
+			"Type Y<Y<capture#1-of ? extends Integer>> inferred for Y<>, is not valid for an anonymous class with '<>'\n" + 
+			"----------\n");
+	
+}
+// instantiate an interface using the anonymous diamond 
+public void testBug488663_007() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		X x = new X(\"Success\");\n" + 
+			"		I<X> i = new I<>() {\n" + 
+			"			public String toString(X x1) {\n" + 
+			"				return x1.name();\n" + 
+			"			}\n" + 
+			"		};\n" + 
+			"		System.out.println(i.toString(x));\n" +
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString(T t);\n" + 
+			"}"
+		},
+		"Success");
+}
+// anonymous diamond instantiating interface as argument to an invocation
+public void testBug488663_008() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	<T> void print(T o, I<T> converter) {\n" + 
+			"		System.out.println(converter.toString(o));\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		X x = new X(\"Success\");\n" + 
+			"		x.print(x, new I<>() {\n" + 
+			"			public String toString(X x1) {\n" + 
+			"				return x1.name();\n" + 
+			"			}\n" + 
+			"		});\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString(T t);\n" + 
+			"}"
+		},
+		"Success");
+}
+// anonymous diamond instantiating an abstract class as argument to an invocation
+public void testBug488663_009() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	<T> void print(T o, I<T> converter) {\n" + 
+			"		System.out.println(converter.toString(o));\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		X x = new X(\"Success\");\n" + 
+			"		x.print(x, new Z<>() {\n" + 
+			"			public String toString(X x1) {\n" + 
+			"				return x1.name();\n" + 
+			"			}\n" + 
+			"		});\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString(T t);\n" + 
+			"}\n" + 
+			"abstract class Z<T> implements I<T> {}\n"
+		},
+		"Success");
+}
+// anonymous diamond with polytype argument
+public void testBug488663_010() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		Y<String> y = new Y<>(() -> System.out.println(\"Done\")) {\n" + 
+			"		};\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface J {\n" + 
+			"	void doSomething();\n" + 
+			"}\n" + 
+			"class Y<T> {\n" + 
+			"	public Y(J j) {\n" + 
+			"		j.doSomething();\n" + 
+			"	}\n" + 
+			"}",
+		},
+		"Done");
+}
+// anonymous diamond with polytype argument
+public void testBug488663_011() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		Y<String> y = new Y<>(Y::foo) {\n" + 
+			"		};\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface J {\n" + 
+			"	void doSomething();\n" + 
+			"}\n" + 
+			"class Y<T> {\n" + 
+			"	public Y(J j) {\n" + 
+			"		j.doSomething();\n" + 
+			"	}\n" + 
+			"	static void foo() {\n" + 
+			"		System.out.println(\"Done\");\n" + 
+			"	}\n" +
+			"}",
+		},
+		"Done");
+}
+// Nested anonymous diamonds - TODO - confirm that this is indeed correct as per spec
+public void testBug488663_012() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		Y<String> y = new Y<>(\"Done\", new I<>() {\n" + 
+			"				public void doSomething(String s) {\n" + 
+			"					System.out.println(s);\n" + 
+			"				}\n" + 
+			"			}){\n" + 
+			"		};\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	void doSomething(T t);\n" + 
+			"}\n" + 
+			"class Y<T> {\n" + 
+			"	public Y(T t, I<T> i) {\n" + 
+			"		i.doSomething(t);\n" + 
+			"	}\n" + 
+			"}",
+		},
+		"Done");
+}
+// Redundant type argument specification - TODO - confirm that this is correct
+public void testBug488663_013() {
+	Map<String, String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, CompilerOptions.ERROR);
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		X x = new X(\"Success\");\n" + 
+			"		I<X> i = new I<X>() {\n" + 
+			"			public String toString(X x1) {\n" + 
+			"				return x1.name();\n" + 
+			"			}\n" + 
+			"		};\n" + 
+			"		System.out.println(i.toString(x));\n" +
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString(T t);\n" + 
+			"}"
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 11)\n" + 
+		"	I<X> i = new I<X>() {\n" + 
+		"	             ^\n" + 
+		"Redundant specification of type arguments <X>\n" + 
+		"----------\n", 
+		null, true, options);
+}
+// All non-private methods of an anonymous class instantiated with '<>' must be treated as being annotated with @override
+public void testBug488663_014() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	String name;\n" + 
+			"	public X(String name) {\n" + 
+			"		this.name = name;\n" + 
+			"	}\n" + 
+			"	<T> void print(T o, I<T> converter) {\n" + 
+			"		System.out.println(converter.toString(o));\n" + 
+			"	}\n" + 
+			"	String name() {\n" + 
+			"		return this.name;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		X x = new X(\"asdasfd\");\n" + 
+			"		x.print(x, new Z<>() {\n" + 
+			"			public String toString(String s) {\n" + 
+			"				return s;\n" + 
+			"			}\n" + 
+			"		});\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString(T t);\n" +
+			"}\n" + 
+			"class Z<T> implements I<T> {\n" +
+			"	public String toString(T t) {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}",
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 15)\n" + 
+		"	public String toString(String s) {\n" + 
+		"	              ^^^^^^^^^^^^^^^^^^\n" + 
+		"The method toString(String) of type new Z<X>(){} must override or implement a supertype method\n" + 
+		"----------\n");
+}
+// Inaccessible type inferred for anonymous diamond is an error
+public void testBug488663_015() {
+	this.runNegativeTest(
+		new String[] {
+			"Test.java",
+			"public class Test<T> {\n" + 
+			"	private static class Inner {" +
+			"		public Inner(){}\n" +	
+			"	}\n" + 
+			"	<R> void print(I<R> i) {}\n" + 
+			"	public Inner get() {\n" + 
+			"		return new Inner();\n" + 
+			"	}\n" + 
+			"}\n",
+			"Z.java",
+			"class Z<T> implements I<T> {\n" + 
+			"	public Z(T t1) {}\n" + 
+			"	public String toString (T t) {\n" + 
+			"		return t.toString();\n" + 
+			"	}\n" + 
+			"}",
+			"X.java",
+			"public class X {\n" +  
+			"	public static void main(String[] args) {\n" + 
+			"		Test<String> t = new Test<>();\n" + 
+			"		t.print(new Z<>(t.get()) {\n" + 
+			"			\n" + 
+			"		});\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString();\n" + 
+			"}"
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 4)\n" + 
+		"	t.print(new Z<>(t.get()) {\n" + 
+		"	            ^^^^^^^^^^^^\n" + 
+		"The type Test$Inner is not visible\n" + 
+		"----------\n");
+}
+// Inaccessible type inferred for anonymous diamond is an error - interface case
+public void testBug488663_016() {
+	this.runNegativeTest(
+		new String[] {
+			"Test.java",
+			"public class Test<T> {\n" + 
+			"	private static class Inner {" +
+			"		public Inner(){}\n" +	
+			"	}\n" + 
+			"	<R extends Inner> void print(I<R> i) {}\n" + 
+			"	public Inner get() {\n" + 
+			"		return new Inner();\n" + 
+			"	}\n" + 
+			"}\n",
+			"X.java",
+			"public class X {\n" +  
+			"	public static void main(String[] args) {\n" + 
+			"		Test<String> t = new Test<>();\n" + 
+			"		t.print(new I<>() {\n" + 
+			"			public String toString() {\n" + 
+			"				return \"\";\n" + 
+			"			}\n" + 
+			"		});\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"interface I<T> {\n" + 
+			"	String toString();\n" + 
+			"}"
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 4)\n" + 
+		"	t.print(new I<>() {\n" + 
+		"	            ^^^^^\n" + 
+		"The type Test$Inner is not visible\n" + 
+		"----------\n");
+}
+public static Class testClass() {
+	return GenericsRegressionTest_9.class;
+}
+
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment.java
index 4eb0b54..e44a4b0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
index 5091e10..18d6faa 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG, IBM Corporation and others.
+ * Copyright (c) 2013, 2016 GK Software AG, IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Stephan Herrmann - initial API and implementation
  *     Jesper S Moller - realigned with bug 399695
@@ -77,6 +81,7 @@
 
 	// default methods with various modifiers, negative cases
 	public void testModifiers1a() {
+		String infMod = this.complianceLevel >= ClassFileConstants.JDK9 ? " private," : "";
 		runNegativeTest(
 		new String[] {
 			"I.java",
@@ -93,17 +98,17 @@
 			"1. ERROR in I.java (at line 5)\n" + 
 			"	public default synchronized void foo2() { System.exit(0); }\n" + 
 			"	                                 ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo2; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo2; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n" + 
 			"2. ERROR in I.java (at line 7)\n" + 
 			"	public default strictfp synchronized void foo4() {}\n" + 
 			"	                                          ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo4; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo4; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n" + 
 			"3. ERROR in I.java (at line 8)\n" + 
 			"	public default strictfp synchronized @Annot void foo5() {}\n" + 
 			"	                                                 ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo5; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo5; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n");
 	}
 
@@ -142,6 +147,7 @@
 
 	// regular interface with illegal modifiers
 	public void testModifiers2() {
+		String infMod = this.complianceLevel >= ClassFileConstants.JDK9 ? " private," : "";
 		runNegativeTest(
 		new String[] {
 			"I.java",
@@ -158,7 +164,7 @@
 			"1. ERROR in I.java (at line 5)\n" +
 			"	public synchronized void foo2();\n" +
 			"	                         ^^^^^^\n" +
-			"Illegal modifier for the interface method foo2; only public, abstract, default, static and strictfp are permitted\n" +
+			"Illegal modifier for the interface method foo2; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" +
 			"----------\n" +
 			"2. ERROR in I.java (at line 6)\n" +
 			"	strictfp void foo3();\n" +
@@ -173,7 +179,7 @@
 			"4. ERROR in I.java (at line 7)\n" +
 			"	public strictfp synchronized void foo4();\n" +
 			"	                                  ^^^^^^\n" +
-			"Illegal modifier for the interface method foo4; only public, abstract, default, static and strictfp are permitted\n" +
+			"Illegal modifier for the interface method foo4; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" +
 			"----------\n" +
 			"5. ERROR in I.java (at line 8)\n" +
 			"	public strictfp synchronized @Annot void foo5();\n" +
@@ -183,12 +189,13 @@
 			"6. ERROR in I.java (at line 8)\n" +
 			"	public strictfp synchronized @Annot void foo5();\n" +
 			"	                                         ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo5; only public, abstract, default, static and strictfp are permitted\n" +
+			"Illegal modifier for the interface method foo5; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" +
 			"----------\n");
 	}
 
 	// default & regular methods with modifiers that are illegal even for default methods
 	public void testModifiers3() {
+		String infMod = this.complianceLevel >= ClassFileConstants.JDK9 ? " private," : "";
 		runNegativeTest(
 		new String[] {
 			"I.java",
@@ -204,7 +211,7 @@
 			"1. ERROR in I.java (at line 2)\n" + 
 			"	native void foo1();\n" + 
 			"	            ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo1; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo1; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n" + 
 			"2. ERROR in I.java (at line 3)\n" + 
 			"	static void foo2();\n" + 
@@ -214,12 +221,12 @@
 			"3. ERROR in I.java (at line 4)\n" + 
 			"	native default void foo3() {}\n" + 
 			"	                    ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo3; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo3; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n" + 
 			"4. ERROR in I.java (at line 5)\n" + 
 			"	default native void foo4() {}\n" + 
 			"	                    ^^^^^^\n" + 
-			"Illegal modifier for the interface method foo4; only public, abstract, default, static and strictfp are permitted\n" + 
+			"Illegal modifier for the interface method foo4; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" + 
 			"----------\n" + 
 			"5. ERROR in I.java (at line 6)\n" + 
 			"	static default void foo5() {}\n" + 
@@ -2133,6 +2140,7 @@
     
     // test for different error messages in modifiers.
 	public void test400977() {
+		String infMod = this.complianceLevel >= ClassFileConstants.JDK9 ? " private," : "";
 		runNegativeTest(
 		new String[] {
 			"I.java",
@@ -2159,7 +2167,7 @@
 			"4. ERROR in I.java (at line 3)\n" +
 			"	public abstract default strictfp final void bar();}\n" +
 			"	                                            ^^^^^\n" +
-			"Illegal modifier for the interface method bar; only public, abstract, default, static and strictfp are permitted\n" +
+			"Illegal modifier for the interface method bar; only public,"+ infMod +" abstract, default, static and strictfp are permitted\n" +
 			"----------\n");
 	}
     // https://bugs.eclipse.org/bugs/show_bug.cgi?id=420084,  [1.8] static interface method cannot be resolved without receiver when imported statically
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest_9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest_9.java
new file mode 100644
index 0000000..439705b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InterfaceMethodsTest_9.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import org.eclipse.jdt.core.tests.junit.extension.TestCase;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
+import junit.framework.Test;
+
+// Bug 488662 - [1.9] Allow private methods in interfaces 
+@SuppressWarnings({ "rawtypes" })
+public class InterfaceMethodsTest_9 extends AbstractComparableTest {
+
+// Static initializer to specify tests subset using TESTS_* static variables
+// All specified tests which do not belong to the class are skipped...
+	static {
+//			TESTS_NAMES = new String[] { "testBug488662_001" };
+//			TESTS_NUMBERS = new int[] { 561 };
+//			TESTS_RANGE = new int[] { 1, 2049 };
+	}
+
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_9);
+	}
+
+	public static Test setUpTest(Test test) throws Exception {
+		TestCase.setUpTest(test);
+		RegressionTestSetup suite = new RegressionTestSetup(ClassFileConstants.JDK9);
+		suite.addTest(test);
+		return suite;
+	}
+
+	public static Class testClass() {
+		return InterfaceMethodsTest_9.class;
+	}
+
+	public InterfaceMethodsTest_9(String name) {
+		super(name);
+	}
+
+	// private method - positive test
+	public void testBug488662_001() {
+		runConformTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"@SuppressWarnings(\"unused\")\n" +			
+			"    private void foo()  {}\n" +
+			"}\n",
+		}, 
+		"");
+	}
+	// private method legal combination of modifiers - positive test
+	public void testBug488662_002() {
+		runConformTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"@SuppressWarnings(\"unused\")\n" +			
+			"    private static void foo()  {}\n" +
+			"}\n",
+		}, 
+		"");
+	}
+	// private method legal combination of modifiers - positive test
+	public void testBug488662_003() {
+		runConformTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"@SuppressWarnings(\"unused\")\n" +			
+			"    private strictfp void foo()  {}\n" +
+			"}\n",
+		}, 
+		"");
+	}
+
+	// missing method body - negative test
+	public void testBug488662_004() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"@SuppressWarnings(\"unused\")\n" +
+			"    private void foo();\n" +
+			"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in I.java (at line 3)\n" +
+			"	private void foo();\n" +
+			"	             ^^^^^\n" +
+			"This method requires a body instead of a semicolon\n" +
+			"----------\n");
+	}
+
+	// illegal modifier combination - negative test
+	public void testBug488662_005() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"@SuppressWarnings(\"unused\")\n" +			
+			"    private default void foo();\n" +
+			"}\n"
+			},
+			"----------\n" + 
+			"1. ERROR in I.java (at line 3)\n" + 
+			"	private default void foo();\n" + 
+			"	                     ^^^^^\n" + 
+			"Illegal combination of modifiers for the private interface method foo; additionally only one of static and strictfp is permitted\n" + 
+			"----------\n" + 
+			"2. ERROR in I.java (at line 3)\n" + 
+			"	private default void foo();\n" + 
+			"	                     ^^^^^\n" + 
+			"This method requires a body instead of a semicolon\n" + 
+			"----------\n");
+	}
+	// illegal modifier combination - negative test
+	public void testBug488662_006() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"	private abstract void foo();\n" +
+			"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in I.java (at line 2)\n" +
+			"	private abstract void foo();\n" +
+			"	                      ^^^^^\n" +
+			"Illegal combination of modifiers for the private interface method foo; additionally only one of static and strictfp is permitted\n" + 
+			"----------\n");
+	}
+
+	// illegal modifier combination - negative test
+	public void testBug488662_007() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"    private synchronized void foo();\n" +
+			"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in I.java (at line 2)\n" + 
+			"	private synchronized void foo();\n" + 
+			"	                          ^^^^^\n" + 
+			"Illegal modifier for the interface method foo; only public, private, abstract, default, static and strictfp are permitted\n" + 
+			"----------\n" + 
+			"2. ERROR in I.java (at line 2)\n" + 
+			"	private synchronized void foo();\n" + 
+			"	                          ^^^^^\n" + 
+			"This method requires a body instead of a semicolon\n" + 
+			"----------\n");
+	}
+
+	// reduced visibility modifier - negative test
+	public void testBug488662_008() {
+		runNegativeTest(
+		new String[] {
+			"X.java",
+			"interface I {\n"+
+			"	public default void foo() {}\n"+
+			"}\n"+
+			"public class X implements I{\n"+
+			"@SuppressWarnings(\"unused\")\n" +			
+			"@Override\n" +
+			"	private void foo() {}\n"+
+			"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 7)\n" +
+			"	private void foo() {}\n"+
+			"	             ^^^^^\n" +
+			"Cannot reduce the visibility of the inherited method from I\n" + 
+			"----------\n");
+	}
+
+
+	// No unimplemented method error - positive test
+	public void testBug488662_009() {
+		runConformTest(
+		new String[] {
+			"X.java",
+			"interface I {\n"+
+			"	private  void foo() {\n"+
+			"	}\n"+
+			"	public default void bar() {\n"+
+			"		foo();\n"+
+			"	}\n"+
+			"}\n"+
+			"public class X implements I{\n"+
+			"	public static void main(String[] args) {\n"+
+			"		new X().bar();\n"+
+			"	}\n"+
+			"}\n"
+		}, 
+		"");
+	}
+	// illegal modifier combination - multiple errors - negative test
+	public void testBug488662_010() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"    private public void foo(){}\n" +
+			"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in I.java (at line 2)\n" +
+			"	private public void foo(){}\n" +
+			"	                    ^^^^^\n" +
+			"Illegal combination of modifiers for the private interface method foo; additionally only one of static and strictfp is permitted\n" + 
+			"----------\n");
+	}
+	// illegal modifier combination - negative test
+	public void testBug488662_011() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"    private protected void foo();\n" +
+			"}\n"
+			},
+			"----------\n" + 
+			"1. ERROR in I.java (at line 2)\n" + 
+			"	private protected void foo();\n" + 
+			"	                       ^^^^^\n" + 
+			"Illegal modifier for the interface method foo; only public, private, abstract, default, static and strictfp are permitted\n" + 
+			"----------\n" + 
+			"2. ERROR in I.java (at line 2)\n" + 
+			"	private protected void foo();\n" + 
+			"	                       ^^^^^\n" + 
+			"This method requires a body instead of a semicolon\n" + 
+			"----------\n");
+	}
+	// illegal modifier combination - multiple errors - negative test
+	public void testBug488662_012() {
+		runNegativeTest(
+		new String[] {
+			"I.java",
+			"public interface I {\n" +
+			"    private private public default protected void foo();\n" +
+			"}\n"
+			},
+			"----------\n" + 
+			"1. ERROR in I.java (at line 2)\n" + 
+			"	private private public default protected void foo();\n" + 
+			"	                                              ^^^^^\n" + 
+			"Duplicate modifier for the method foo in type I\n" + 
+			"----------\n" + 
+			"2. ERROR in I.java (at line 2)\n" + 
+			"	private private public default protected void foo();\n" + 
+			"	                                              ^^^^^\n" + 
+			"Illegal modifier for the interface method foo; only public, private, abstract, default, static and strictfp are permitted\n" + 
+			"----------\n" + 
+			"3. ERROR in I.java (at line 2)\n" + 
+			"	private private public default protected void foo();\n" + 
+			"	                                              ^^^^^\n" + 
+			"This method requires a body instead of a semicolon\n" + 
+			"----------\n");
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
index 3265f9a..17bbc8f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Jesper Steen Moller - initial API and implementation
  *            Bug 416885 - [1.8][compiler]IncompatibleClassChange error (edit)
@@ -21,14 +25,22 @@
 import org.eclipse.jdt.core.tests.util.Util;
 import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
 import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
 @SuppressWarnings({ "unchecked", "rawtypes" })
 public class JSR335ClassFileTest extends AbstractComparableTest {
 
+	String versionString = null;
+
 public JSR335ClassFileTest(String name) {
 	super(name);
 }
+// No need for a tearDown()
+protected void setUp() throws Exception {
+	super.setUp();
+	this.versionString = (this.complianceLevel < ClassFileConstants.JDK9) ? "version 1.8 : 52.0" : "version 9 : 53.0";
+}
 
 /*
  * Toggle compiler in mode -1.8
@@ -77,7 +89,7 @@
 	);
 
 	String expectedOutput =
-		"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+		"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 		"public class X {\n" + 
 		"  Constant pool:\n" + 
 		"    constant #1 class: #2 X\n" + 
@@ -184,7 +196,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -293,7 +305,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -398,7 +410,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -520,7 +532,7 @@
 		},
 	"SUCCESS"
 	);
-	verifyClassFile(			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+	verifyClassFile("// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -634,7 +646,7 @@
 	"SUCCESS"
 	);
 	String expected =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -745,7 +757,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -868,7 +880,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -990,7 +1002,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1109,7 +1121,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1261,7 +1273,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1429,7 +1441,7 @@
 	);
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1597,7 +1609,7 @@
 		"");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1759,7 +1771,7 @@
 		"");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -1898,7 +1910,7 @@
 		"");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -2092,7 +2104,7 @@
 		"");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"public class X {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X\n" + 
@@ -2334,7 +2346,7 @@
 		"Lambda");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"class X$1Y {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X$1Y\n" + 
@@ -2511,7 +2523,7 @@
 		"Lambda");
 
 	String expectedOutput =
-			"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 			"class X$1Y {\n" + 
 			"  Constant pool:\n" + 
 			"    constant #1 class: #2 X$1Y\n" + 
@@ -2934,7 +2946,7 @@
 			"m(bridge method(i))");
 		
 		String expectedOutput =
-						"// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + 
+						"// Compiled from X.java (" + this.versionString + ", super bit)\n" + 
 						"public class X {\n" + 
 						"  Constant pool:\n" + 
 						"    constant #1 class: #2 X\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
index 0d9f6a1..9025cea 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -1020,6 +1024,9 @@
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=406641, [1.8][compiler][codegen] Code generation for intersection cast.
 public void test039() {
+	String errMsg = isJRE9 ?
+			"X (in module: Unnamed Module) cannot be cast to I (in module: Unnamed Module)" :
+				"X cannot be cast to I";
 	this.runConformTest(
 			new String[] {
 					"X.java",
@@ -1040,7 +1047,7 @@
 					"	}\n" +
 					"}\n",
 				},
-				"X cannot be cast to I");
+				errMsg);
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=406773, [1.8][compiler][codegen] "java.lang.IncompatibleClassChangeError" caused by attempted invocation of private constructor
 public void test041() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodParametersAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodParametersAttributeTest.java
index dd5e3ea..c89aa32 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodParametersAttributeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodParametersAttributeTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 Jesper Steen Moeller and others.
+ * Copyright (c) 2013, 2016 Jesper Steen Moeller and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Jesper Steen Moeller - initial API and implementation
  *******************************************************************************/
@@ -19,17 +23,23 @@
 import org.eclipse.jdt.core.ToolFactory;
 import org.eclipse.jdt.core.tests.util.Util;
 import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
-@SuppressWarnings({ "unchecked", "rawtypes" })
 public class MethodParametersAttributeTest extends AbstractRegressionTest {
+	String versionString = null;
 	public MethodParametersAttributeTest(String name) {
 		super(name);
 	}
-
+	// No need for a tearDown()
+	protected void setUp() throws Exception {
+		super.setUp();
+		this.versionString = (this.complianceLevel < ClassFileConstants.JDK9) ? "version 1.8 : 52.0" : "version 9 : 53.0";
+	}
+	@SuppressWarnings("rawtypes")
 	public static Class testClass() {
 		return MethodParametersAttributeTest.class;
 	}
@@ -377,7 +387,7 @@
 				ClassFileBytesDisassembler.DETAILED);
 	
 		String expectedOutput =
-				"// Compiled from ParameterNames.java (version 1.8 : 52.0, super bit)\n" + 
+				"// Compiled from ParameterNames.java (" + this.versionString + ", super bit)\n" + 
 				"public class ParameterNames {\n" + 
 				"  \n" + 
 				"  // Method descriptor #6 ()V\n" + 
@@ -463,7 +473,7 @@
 				ClassFileBytesDisassembler.DETAILED);
 
 		String expectedOutput =
-			"// Compiled from ParameterNames.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from ParameterNames.java (" + this.versionString + ", super bit)\n" + 
 			"// Signature: Ljava/lang/Object;Ljava/util/concurrent/Callable<Ljava/lang/String;>;\n" + 
 			"class ParameterNames$1 implements java.util.concurrent.Callable {\n" + 
 			"  \n" + 
@@ -543,7 +553,7 @@
 				ClassFileBytesDisassembler.DETAILED);
 
 		String expectedOutput =
-			"// Compiled from FancyEnum.java (version 1.8 : 52.0, super bit)\n" + 
+			"// Compiled from FancyEnum.java (" + this.versionString + ", super bit)\n" + 
 			"// Signature: Ljava/lang/Enum<LFancyEnum;>;\n" + 
 			"public final enum FancyEnum {\n" + 
 			"  \n" + 
@@ -935,7 +945,7 @@
 	}
 
 	private void runParameterNameTest(String fileName, String body) {
-		Map compilerOptions = getCompilerOptions();
+		Map<String, String> compilerOptions = getCompilerOptions();
 		compilerOptions.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
 		compilerOptions.put(CompilerOptions.OPTION_MethodParametersAttribute, CompilerOptions.GENERATE);
 		this.runConformTest(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
index 4b1422e..b6a3f61 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -1926,7 +1930,7 @@
 				"public class X {\n" +
 				"	void test() {\n" +
 				"		Pair<Double, Integer> p = new InvertedPair<Integer, Double>();\n" +
-				"		p.setA(new Double(1.1));\n" +
+				"		p.setA(Double.valueOf(1.1));\n" +
 				"	}\n" +
 				"}\n" +
 				"class Pair<A, B> {\n" +
@@ -2991,7 +2995,7 @@
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
-				"public class X { void test(E<Integer,Integer> e) { e.id(new Integer(1)); } }\n" +
+				"public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(1)); } }\n" +
 				"abstract class C<A> { public abstract void id(A x); }\n" +
 				"interface I<B> { void id(B x); }\n" +
 				"abstract class E<A, B> extends C<A> implements I<B> {}\n"
@@ -3012,7 +3016,7 @@
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
-				"public class X { void test(E<Integer,Integer> e) { e.id(new Integer(1)); } }\n" +
+				"public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(1)); } }\n" +
 				"class C<A> { public void id(A x) {} }\n" +
 				"interface I<B> { void id(B x); }\n" +
 				"abstract class E<A, B> extends C<A> implements I<B> {}\n"
@@ -3030,14 +3034,14 @@
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
-				"public class X { void test(E<Integer,Integer> e) { e.id(new Integer(2)); } }\n" +
+				"public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(2)); } }\n" +
 				"abstract class C<A extends Number> { public abstract void id(A x); }\n" +
 				"interface I<B> { void id(B x); }\n" +
 				"abstract class E<A extends Number, B> extends C<A> implements I<B> {}\n"
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 1)\n" +
-			"	public class X { void test(E<Integer,Integer> e) { e.id(new Integer(2)); } }\n" +
+			"	public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(2)); } }\n" +
 			"	                                                     ^^\n" +
 			"The method id(Integer) is ambiguous for the type E<Integer,Integer>\n" +
 			"----------\n"
@@ -3049,14 +3053,14 @@
 		this.runNegativeTest(
 			new String[] {
 				"X.java",
-				"public class X { void test(E<Integer,Integer> e) { e.id(new Integer(111)); } }\n" +
+				"public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(111)); } }\n" +
 				"abstract class C<A extends Number> { public void id(A x) {} }\n" +
 				"interface I<B> { void id(B x); }\n" +
 				"class E<A extends Number, B> extends C<A> implements I<B> { public void id(B b) {} }\n"
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 1)\n" +
-			"	public class X { void test(E<Integer,Integer> e) { e.id(new Integer(111)); } }\n" +
+			"	public class X { void test(E<Integer,Integer> e) { e.id(Integer.valueOf(111)); } }\n" +
 			"	                                                     ^^\n" +
 			"The method id(Integer) is ambiguous for the type E<Integer,Integer>\n" +
 			"----------\n"
@@ -3069,12 +3073,12 @@
 			new String[] {
 				"X.java",
 				"public class X {\n" +
-				"	void test(E<Integer,Integer> e) { e.id(new Integer(111)); }\n" +
+				"	void test(E<Integer,Integer> e) { e.id(Integer.valueOf(111)); }\n" +
 				"	void test(M<Integer,Integer> m) {\n" +
-				"		m.id(new Integer(111));\n" +
-				"		((E<Integer, Integer>) m).id(new Integer(111));\n" +
+				"		m.id(Integer.valueOf(111));\n" +
+				"		((E<Integer, Integer>) m).id(Integer.valueOf(111));\n" +
 				"	}\n" +
-				"	void test(N<Integer> n) { n.id(new Integer(111)); }\n" +
+				"	void test(N<Integer> n) { n.id(Integer.valueOf(111)); }\n" +
 				"}\n" +
 				"abstract class C<A extends Number> { public void id(A x) {} }\n" +
 				"interface I<B> { void id(B x); }\n" +
@@ -3084,7 +3088,7 @@
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 4)\n" +
-			"	m.id(new Integer(111));\n" +
+			"	m.id(Integer.valueOf(111));\n" +
 			"	  ^^\n" +
 			"The method id(Integer) is ambiguous for the type M<Integer,Integer>\n" +
 			"----------\n"
@@ -3279,7 +3283,7 @@
 				"X.java",
 				"public class X {\n" +
 				"	void test(M<Integer,Integer> m) {\n" +
-				"		m.id(new Integer(111));\n" +
+				"		m.id(Integer.valueOf(111));\n" +
 				"	}\n" +
 				"}\n" +
 				"abstract class C<T1 extends Number> { public void id(T1 x) {} }\n" +
@@ -3289,7 +3293,7 @@
 			},
 			"----------\n" +
 			"1. ERROR in X.java (at line 3)\n" +
-			"	m.id(new Integer(111));\n" +
+			"	m.id(Integer.valueOf(111));\n" +
 			"	  ^^\n" +
 			"The method id(Integer) is ambiguous for the type M<Integer,Integer>\n" +
 			"----------\n"
@@ -5514,14 +5518,14 @@
 				"public class Try {\n" +
 				"	public static void main(String[] args) {\n" +
 				"		Ex<String> ex = new Ex<String>();\n" +
-				"		ex.one(\"eclipse\", new Integer(1));\n" +
-				"		ex.two(new Integer(1));\n" +
+				"		ex.one(\"eclipse\", Integer.valueOf(1));\n" +
+				"		ex.two(Integer.valueOf(1));\n" +
 				"		ex.three(\"eclipse\");\n" +
 				"		ex.four(\"eclipse\");\n" +
 				"		System.out.print(',');\n" +
 				"		Ex ex2 = ex;\n" +
-				"		ex2.one(\"eclipse\", new Integer(1));\n" + // unchecked warning
-				"		ex2.two(new Integer(1));\n" + // unchecked warning
+				"		ex2.one(\"eclipse\", Integer.valueOf(1));\n" + // unchecked warning
+				"		ex2.two(Integer.valueOf(1));\n" + // unchecked warning
 				"		ex2.three(\"eclipse\");\n" + // unchecked warning
 				"		ex2.four(\"eclipse\");\n" + // unchecked warning
 				"	}\n" +
@@ -5546,13 +5550,13 @@
 			"Ex is a raw type. References to generic type Ex<C> should be parameterized\n" +
 			"----------\n" +
 			"2. WARNING in Try.java (at line 10)\n" +
-			"	ex2.one(\"eclipse\", new Integer(1));\n" +
-			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"	ex2.one(\"eclipse\", Integer.valueOf(1));\n" +
+			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Type safety: The method one(Object, Object) belongs to the raw type Ex. References to generic type Ex<C> should be parameterized\n" +
 			"----------\n" +
 			"3. WARNING in Try.java (at line 11)\n" +
-			"	ex2.two(new Integer(1));\n" +
-			"	^^^^^^^^^^^^^^^^^^^^^^^\n" +
+			"	ex2.two(Integer.valueOf(1));\n" +
+			"	^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
 			"Type safety: The method two(Object) belongs to the raw type Ex. References to generic type Ex<C> should be parameterized\n" +
 			"----------\n" +
 			"4. WARNING in Try.java (at line 12)\n" +
@@ -5846,6 +5850,8 @@
 	}
 	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=101049
 	public void test070() {
+		Map<String,String> options = getCompilerOptions();
+		options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 		this.runConformTest(
 			true,
 			new String[] {
@@ -5858,7 +5864,7 @@
 				"		try { return c.newInstance(); } catch(Exception e) { return null; }\n" +
 				"	}\n" +
 				"}\n"
-			},
+			}, null, options,
 			"----------\n" +
 			"1. WARNING in BooleanFactory.java (at line 5)\n" +
 			"	public <U extends Boolean> U create(Class<U> c) {\n" +
@@ -14317,7 +14323,9 @@
 		"	                      ^^^^^^^^^^^^^^^^^^^^^^\n" +
 		(this.complianceLevel < ClassFileConstants.JDK1_8
 		? "Illegal modifier for the interface method a; only public & abstract are permitted\n"
-		: "Illegal modifier for the interface method a; only public, abstract, default, static and strictfp are permitted\n"
+		: this.complianceLevel < ClassFileConstants.JDK9 ? 
+				"Illegal modifier for the interface method a; only public, abstract, default, static and strictfp are permitted\n" :
+				"Illegal modifier for the interface method a; only public, private, abstract, default, static and strictfp are permitted\n"
 		) +
 		"----------\n" + 
 		"----------\n" + 
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
new file mode 100644
index 0000000..b6768ae
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -0,0 +1,1577 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.tests.util.Util;
+
+import junit.framework.Test;
+
+public class ModuleCompilationTests extends BatchCompilerTest {
+
+	static {
+//		 TESTS_NAMES = new String[] { "test035" };
+		// TESTS_NUMBERS = new int[] { 1 };
+		// TESTS_RANGE = new int[] { 298, -1 };
+	}
+
+	public ModuleCompilationTests(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_9);
+	}
+
+	public static Class testClass() {
+		return ModuleCompilationTests.class;
+	}
+
+	protected void writeFile(String directoryName, String fileName, String source) {
+		File directory = new File(directoryName);
+		if (!directory.exists()) {
+			if (!directory.mkdirs()) {
+				System.out.println("Could not create " + directoryName);
+				return;
+			}
+		}
+		String filePath = directory.getAbsolutePath() + File.separator + fileName;
+		try {
+			BufferedWriter writer = new BufferedWriter(new FileWriter(filePath));
+			writer.write(source);
+			writer.flush();
+			writer.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			return;
+		}
+	}
+
+	public void test001() {
+		this.runNegativeTest(
+			new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"     java.sql.Connection con = null;\n" +
+				"	}\n" +
+				"}",
+				"module-info.java",
+				"module mod.one { \n" +
+				"	requires java.base;\n" +
+				"}"
+	        },
+			"\"" + OUTPUT_DIR +  File.separator + "module-info.java\" "
+	        + "\"" + OUTPUT_DIR +  File.separator + "p/X.java\"",
+	        "",
+	        "----------\n" + 
+    		"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/p/X.java (at line 4)\n" + 
+    		"	java.sql.Connection con = null;\n" + 
+    		"	^^^^^^^^\n" + 
+    		"java.sql cannot be resolved to a type\n" + 
+    		"----------\n" + 
+    		"1 problem (1 error)\n",
+	        true);
+	}
+	public void test002() {
+		this.runConformTest(
+			new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"     java.sql.Connection con = null;\n" +
+				"     System.out.println(con);\n" +
+				"	}\n" +
+				"}",
+				"module-info.java",
+				"module mod.one { \n" +
+				"	requires java.base;\n" +
+				"	requires java.sql;\n" +
+				"}"
+	        },
+			"\"" + OUTPUT_DIR +  File.separator + "module-info.java\" "
+	        + "\"" + OUTPUT_DIR +  File.separator + "p/X.java\"",
+	        "",
+	        "",
+	        true);
+	}
+	public void test003() {
+		this.runConformTest(
+			new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"     java.sql.Connection con = null;\n" +
+				"     System.out.println(con);\n" +
+				"	}\n" +
+				"}",
+	        },
+	        "\"" + OUTPUT_DIR +  File.separator + "p/X.java\"",
+	        "",
+	        "",
+	        true);
+	}
+	public void test004() {
+		this.runConformTest(
+			new String[] {
+				"module-info.java",
+				"module mod.one { \n" +
+				"	requires java.base;\n" +
+				"	requires java.sql;\n" +
+				"}"
+	        },
+			"\"" + OUTPUT_DIR +  File.separator + "module-info.java\"",
+	        "",
+	        "",
+	        true);
+		String fileName = OUTPUT_DIR + File.separator + "module-info.class";
+		assertTrue("Missing modul-info.class: " + fileName, (new File(fileName)).exists());
+	}
+	public void test005() {
+		String out = "bin";
+		this.runConformTest(
+			new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"public class X {\n" +
+				"	java.sql.Connection con;\n" +
+				"}",
+				"module-info.java",
+				"module mod.one { \n" +
+				"	requires java.base;\n" +
+				"	requires java.sql;\n" +
+				"	requires java.desktop;\n" +
+				"}",
+				"q/Y.java",
+				"package q;\n" +
+				"public class Y {\n" +
+				"   java.awt.Image image;\n" +
+				"}"
+	        },
+			"\"" + OUTPUT_DIR + File.separator + "module-info.java\" "
+			+ "\"" + OUTPUT_DIR + File.separator + "q/Y.java\" "
+	        + "\"" + OUTPUT_DIR + File.separator + "p/X.java\" "
+	        + "-d " + OUTPUT_DIR + File.separator + out,
+	        "",
+	        "",
+	        true);
+		String fileName = OUTPUT_DIR + File.separator + out + File.separator + "module-info.class";
+		assertTrue("Missing modul-info.class: " + fileName, (new File(fileName)).exists());
+	}
+	public void test006() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"	requires java.desktop;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	java.sql.Connection con;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.awt.Image image;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + OUTPUT_DIR + File.separator + out );
+			buffer.append(" -9 ");
+		buffer.append(" -classpath \"")
+		.append(Util.getJavaClassLibsAsString())
+		.append("\" ");
+		buffer.append(" --module-source-path " + "\"" + directory + "\"");
+		runConformTest(new String[]{}, buffer.toString(), "", "", false);
+	}
+	public void test007() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"	requires mod.one;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\n" +
+						"}");
+		
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + OUTPUT_DIR + File.separator + out );
+			buffer.append(" -9 ");
+		buffer.append(" -classpath \"")
+		.append(Util.getJavaClassLibsAsString())
+		.append("\" ");
+		buffer.append(" --module-source-path " + "\"" + directory + "\"");
+		
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\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" + 
+				"The type p.X is not visible\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	public void test008() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	exports p;\n" +
+						"	requires mod.two;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"import q.Y;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return Y.con;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	exports q;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   public static java.sql.Connection con = null;\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 + "\"");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test008a() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	exports p.q;\n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p" + File.separator + "q", "X.java", 
+						"package p.q;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"	requires mod.one;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q" + File.separator + "r", "Y.java", 
+						"package q.r;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.q.X.getConnection();\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append("--system ").append("C:\\Java\\jdk-9-ea+153")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test009() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	exports p;\n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"	requires mod.one;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	private void createReusableModules(String srcDir, String outDir, File modDir) {
+		String moduleLoc = srcDir + File.separator + "mod.one";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	exports p;\n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		// This one is not exported (i.e. internal to this module)
+		writeFile(moduleLoc + File.separator + "p1", "X1.java", 
+				"package p1;\n" +
+				"public class X1 {\n" +
+				"	public static java.sql.Connection getConnection() {\n" +
+				"		return null;\n" +
+				"	}\n" +
+				"}");
+
+		moduleLoc = srcDir + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	exports q;\n" +
+						"	requires java.base;\n" +
+						"	requires mod.one;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + outDir )
+			.append(" -9 ")
+			.append(" --module-path \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + srcDir + "\"");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+
+		String fileName = modDir + File.separator + "mod.one.jar";
+		try {
+			Util.zip(new File(outDir + File.separator + "mod.one"), 
+								fileName);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		if (!modDir.exists()) {
+			if (!modDir.mkdirs()) {
+				fail("Coult not create folder " + modDir);
+			}
+		}
+		File mod2 = new File(modDir, "mod.two");
+		if (!mod2.mkdir()) {
+			fail("Coult not create folder " + mod2);
+		}
+		Util.copy(outDir + File.separator + "mod.two", mod2.getAbsolutePath());
+
+		Util.flushDirectoryContent(new File(outDir));
+		Util.flushDirectoryContent(new File(srcDir));
+	}
+	public void test010() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		File modDir = new File(OUTPUT_DIR + File.separator + "mod");
+		createReusableModules(srcDir, outDir, modDir);
+		String moduleLoc = srcDir + File.separator + "mod.three";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.three { \n" +
+						"	requires mod.one;\n" +
+						"	requires mod.two;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "Z.java", 
+						"package r;\n" +
+						"public class Z extends Object {\n" +
+						"	p.X x = null;\n" +
+						"	q.Y y = null;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + outDir )
+			.append(" -9 ")
+			.append(" -p \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append(modDir.getAbsolutePath())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + srcDir + "\"");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=487421
+	public void test011() {
+		this.runConformTest(
+			new String[] {
+				"p/X.java",
+				"package p;\n" +
+				"public class X {\n" +
+				"   java.lang.SecurityManager man = null;\n" +
+				"}",
+				"module-info.java",
+				"module mod.one { \n" +
+				"	requires java.base;\n" +
+				"}"
+	        },
+			"\"" + OUTPUT_DIR +  File.separator + "module-info.java\" "
+	        + "\"" + OUTPUT_DIR +  File.separator + "p/X.java\"",
+	        "",
+	        "",
+	        true);
+	}
+	// Modules used as regular -classpath (as opposed to --module-path) and module-info referencing
+	// those modules are reported as missing.
+	public void test012() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		File modDir = new File(OUTPUT_DIR + File.separator + "mod");
+		createReusableModules(srcDir, outDir, modDir);
+		String moduleLoc = srcDir + File.separator + "mod.three";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.three { \n" +
+						"	requires mod.one;\n" +
+						"	requires mod.two;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "r", "Z.java", 
+						"package r;\n" +
+						"public class Z extends Object {\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + outDir )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append(modDir + File.separator + "mod.one.jar").append(File.pathSeparator)
+			.append(modDir + File.separator + "mod.two").append(File.pathSeparator)
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + srcDir + "\"");
+
+		runNegativeTest(new String[]{},
+				buffer.toString(), 
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.three/module-info.java (at line 2)\n" + 
+				"	requires mod.one;\n" + 
+				"	         ^^^^^^^\n" + 
+				"mod.one cannot be resolved to a module\n" + 
+				"----------\n" + 
+				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.three/module-info.java (at line 3)\n" + 
+				"	requires mod.two;\n" + 
+				"	         ^^^^^^^\n" + 
+				"mod.two cannot be resolved to a module\n" + 
+				"----------\n" + 
+				"2 problems (2 errors)\n",
+				false);
+	}
+	// Modules used as regular -classpath as opposed to --module-path. The files being compiled
+	// aren't part of any modules (i.e. module-info is missing). The files should be able to
+	// reference the types from referenced classpath.
+	public void test013() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		File modDir = new File(OUTPUT_DIR + File.separator + "mod");
+		createReusableModules(srcDir, outDir, modDir);
+		String moduleLoc = srcDir + File.separator + "mod.three";
+		writeFile(moduleLoc + File.separator + "p", "Z.java", 
+						"package r;\n" +
+						"public class Z extends Object {\n" +
+						"	p.X x = null;\n" +
+						"	q.Y y = null;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+			buffer.append("-d " + outDir )
+			.append(" -9")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append(modDir + File.separator + "mod.one.jar").append(File.pathSeparator)
+			.append(modDir + File.separator + "mod.two").append(File.pathSeparator)
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + srcDir + "\"");
+		runConformTest(new String[]{},
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=495500
+	//-source 9
+	public void testBug495500a() throws Exception {
+		this.runConformTest(
+			new String[] {
+				"X.java",
+				"/** */\n" +
+				"public class X {\n" +
+				"}",
+			},
+	  "\"" + OUTPUT_DIR +  File.separator + "X.java\""
+	  + " -9 -d \"" + OUTPUT_DIR + "\"",
+	  "",
+	  "",
+	  true);
+		String expectedOutput = "// Compiled from X.java (version 9 : 53.0, super bit)";
+		checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
+	}
+	//-source 8 -target 9
+	public void testBug495500b() throws Exception {
+		this.runConformTest(
+			new String[] {
+				"X.java",
+				"/** */\n" +
+				"public class X {\n" +
+				"}",
+			},
+	"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+	+ " -9 -source 8 -target 9 -d \"" + OUTPUT_DIR + "\"",
+	"",
+	"",
+	true);
+		String expectedOutput = "// Compiled from X.java (version 9 : 53.0, super bit)";
+		checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
+	}
+	// compliance 9 -source 9 -target 9
+	public void testBug495500c() throws Exception {
+		this.runConformTest(
+			new String[] {
+				"X.java",
+				"/** */\n" +
+				"public class X {\n" +
+				"}",
+			},
+	"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+	+ " -9 -source 9 -target 9 -d \"" + OUTPUT_DIR + "\"",
+	"",
+	"",
+	true);
+		String expectedOutput = "// Compiled from X.java (version 9 : 53.0, super bit)";
+		checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
+	}
+	public void test014() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"	requires mod.one;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test015() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\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" + 
+				"The type p.X is not visible\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	public void test016() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two")
+			.append(" --add-reads mod.two=mod.one");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test017() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.three")
+			.append(" --add-reads mod.two=mod.one");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\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" + 
+				"The type p.X is not visible\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	public void test018() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.three";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.three { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "r", "Z.java", 
+						"package r;\n" +
+						"public class Z {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two,mod.three")
+			.append(" --add-reads mod.two=mod.one")
+			.append(" --add-reads mod.three=mod.one");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	/*
+	 * Unnamed module tries to access a type from an unexported package successfully. 
+	 */
+	public void test019() {
+		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";
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public abstract class X extends com.sun.security.ntlm.Server {\n" +
+						"	//public X() {}\n" +
+						"	public X(String arg0, String arg1) throws com.sun.security.ntlm.NTLMException {\n" +
+						"		super(arg0, arg1);\n" +
+						"	}\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" -sourcepath " + "\"" + moduleLoc + "\" ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test020() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\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 + "\"")
+			.append(" --add-exports mod.one=mod.two,mod.three");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(),
+				"",
+				"incorrectly formatted option: --add-exports mod.one=mod.two,mod.three\n",
+				false);
+	}
+	public void test021() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\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 + "\"")
+			.append(" --add-reads mod.one/mod.two");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"incorrectly formatted option: --add-reads mod.one/mod.two\n",
+				false);
+	}
+	public void test022() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.three")
+			.append(" --add-exports mod.one/p=mod.three");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"can specify a package in a module only once with --add-export\n",
+				false);
+	}
+	public void test023() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append("\"" + OUTPUT_DIR +  File.separator + "module-info.java\" ")
+			.append(" -extdirs " + OUTPUT_DIR + File.separator + "src");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"option -extdirs not supported at compliance level 9 and above\n",
+				false);
+	}
+	public void test024() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" \"" + OUTPUT_DIR +  File.separator + "module-info.java\" ")
+			.append(" -bootclasspath " + OUTPUT_DIR + File.separator + "src");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"option -bootclasspath not supported at compliance level 9 and above\n",
+				false);
+	}
+	public void test025() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append("\"" + OUTPUT_DIR +  File.separator + "module-info.java\" ")
+			.append(" -endorseddirs " + OUTPUT_DIR + File.separator + "src");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"option -endorseddirs not supported at compliance level 9 and above\n",
+				false);
+	}
+	public void test026() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires transitive java.sql;\n" +
+						"}");
+		String javaHome = System.getProperty("java.home");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" --system \"").append(javaHome).append("\"")
+			.append(" \"" + moduleLoc +  File.separator + "module-info.java\" ");
+
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+	public void test027() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"}");
+		String javaHome = System.getProperty("java.home");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" --system \"").append(javaHome).append(File.separator)
+			.append("lib\"")
+			.append(" \"" + moduleLoc +  File.separator + "module-info.java\" ");
+
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\n"+
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 1)\n"+
+				"	module mod.one { \n"+
+				"	^\n"+
+				"The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files\n"+
+				"----------\n"+
+				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 2)\n"+
+				"	requires java.base;\n"+
+				"	         ^^^^^^^^^\n"+
+				"java.base cannot be resolved to a module\n"+
+				"----------\n"+
+				"2 problems (2 errors)\n",
+				false);
+	}
+	/**
+	 * Mixed case of exported and non exported packages being referred to in another module
+	 */
+	public void test028() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		File modDir = new File(OUTPUT_DIR + File.separator + "mod");
+		createReusableModules(srcDir, outDir, modDir);
+		String moduleLoc = srcDir + File.separator + "mod.three";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.three { \n" +
+						"	requires mod.one;\n" +
+						"	requires mod.two;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "r", "Z.java", 
+						"package r;\n" +
+						"public class Z extends Object {\n" +
+						"	p.X x = null;\n" +
+						"	p1.X1 x1 = null;\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+		.append(" -9 ")
+		.append(" -p \"")
+		.append(Util.getJavaClassLibsAsString())
+		.append(modDir.getAbsolutePath())
+		.append("\" ")
+		.append(" --module-source-path " + "\"" + srcDir + "\"");
+
+		runNegativeTest(new String[]{},
+				buffer.toString(), 
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.three/r/Z.java (at line 4)\n"+
+				"	p1.X1 x1 = null;\n" + 
+				"	^^\n" + 
+				"p1 cannot be resolved to a type\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	public void test029() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"public class Y {\n" +
+						"   java.sql.Connection con = p.X.getConnection();\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two,mod.three")
+			.append(" --add-reads mod.two=mod.one");
+
+		runNegativeTest(new String[]{}, 
+			buffer.toString(), 
+			"",
+			"----------\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"+
+			"java.sql cannot be resolved to a type\n"+
+			"----------\n"+
+			"1 problem (1 error)\n",
+			false);
+	}
+	public void test030() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"import java.sql.*;\n" +
+						"public class Y {\n" +
+						"   Connection con = null;\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two,mod.three")
+			.append(" --add-reads mod.two=mod.one");
+
+		runNegativeTest(new String[]{}, 
+			buffer.toString(), 
+			"",
+			"----------\n"+
+			"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 2)\n"+
+			"	import java.sql.*;\n"+
+			"	       ^^^^^^^^\n"+
+			"The import java.sql cannot be resolved\n"+
+			"----------\n"+
+			"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 4)\n"+
+			"	Connection con = null;\n"+
+			"	^^^^^^^^^^\n"+
+			"Connection cannot be resolved to a type\n"+
+			"----------\n"+
+			"2 problems (2 errors)\n",
+			false);
+	}
+	public void test031() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X {\n" +
+						"	public static java.sql.Connection getConnection() {\n" +
+						"		return null;\n" +
+						"	}\n" +
+						"}");
+		moduleLoc = directory + File.separator + "mod.two";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.two { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "q", "Y.java", 
+						"package q;\n" +
+						"import java.sql.Connection;\n" +
+						"public class Y {\n" +
+						"   Connection con = null;\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 + "\"")
+			.append(" --add-exports mod.one/p=mod.two,mod.three")
+			.append(" --add-reads mod.two=mod.one");
+
+		runNegativeTest(new String[]{}, 
+			buffer.toString(), 
+			"",
+			"----------\n"+
+			"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 2)\n"+
+			"	import java.sql.Connection;\n"+
+			"	       ^^^^^^^^\n"+
+			"The import java.sql cannot be resolved\n"+
+			"----------\n"+
+			"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 4)\n"+
+			"	Connection con = null;\n"+
+			"	^^^^^^^^^^\n"+
+			"Connection cannot be resolved to a type\n"+
+			"----------\n"+
+			"2 problems (2 errors)\n",
+			false);
+	}
+	public void test032() {
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"}");
+		writeFile(moduleLoc, "X.java", 
+						"public class X {\n" +
+						"	public static class Inner {\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 + "\"");
+
+		runConformTest(new String[]{}, 
+			buffer.toString(), 
+			"",
+			"",
+			false);
+	}
+	/**
+	 * Test that a module can't access types/packages in a plain Jar put in classpath
+	 */
+	public void test033() {
+		File libDir = new File(LIB_DIR);
+		Util.delete(libDir); // make sure we recycle the libs
+ 		libDir.mkdirs();
+		try {
+			Util.createJar(
+				new String[] {
+					"a/A.java",
+					"package a;\n" +
+					"public class A {\n" +
+					"}"
+				},
+				LIB_DIR + "/lib1.jar",
+				JavaCore.VERSION_9);
+		} catch (IOException e) {
+			// ignore
+		}
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X extends a.A {\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append(LIB_DIR).append(File.separator).append("lib1.jar").append(File.pathSeparator).append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/X.java (at line 2)\n" + 
+				"	public class X extends a.A {\n" + 
+				"	                       ^\n" + 
+				"a cannot be resolved to a type\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	/**
+	 * Test that a module can't access types/packages in a plain Jar put in modulepath
+	 * but not explicitly added to the "requires" clause
+	 */
+	public void test034() {
+		File libDir = new File(LIB_DIR);
+		Util.delete(libDir); // make sure we recycle the libs
+ 		libDir.mkdirs();
+		try {
+			Util.createJar(
+				new String[] {
+					"a/A.java",
+					"package a;\n" +
+					"public class A {\n" +
+					"}"
+				},
+				LIB_DIR + "/lib1.jar",
+				JavaCore.VERSION_9);
+		} catch (IOException e) {
+			// ignore
+		}
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X extends a.A {\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString()).append("\" ")
+			.append("-p \"")
+			.append(LIB_DIR).append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+		runNegativeTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/X.java (at line 2)\n" + 
+				"	public class X extends a.A {\n" + 
+				"	                       ^\n" + 
+				"a cannot be resolved to a type\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false);
+	}
+	/**
+	 * Test that a module can access types/packages in a plain Jar put in modulepath
+	 * and explicitly added to the "requires" clause
+	 */
+	public void test035() {
+		File libDir = new File(LIB_DIR);
+		Util.delete(libDir); // make sure we recycle the libs
+ 		libDir.mkdirs();
+		try {
+			Util.createJar(
+				new String[] {
+					"a/A.java",
+					"package a;\n" +
+					"public class A {\n" +
+					"}"
+				},
+				LIB_DIR + "/lib1.jar",
+				JavaCore.VERSION_9);
+		} catch (IOException e) {
+			// ignore
+		}
+		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";
+		writeFile(moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						"	requires java.base;\n" +
+						"	requires java.sql;\n" +
+						"	requires lib1;\n" +
+						"}");
+		writeFile(moduleLoc + File.separator + "p", "X.java", 
+						"package p;\n" +
+						"public class X extends a.A {\n" +
+						"}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString()).append("\" ")
+			.append("-p \"")
+			.append(LIB_DIR).append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\"");
+		runConformTest(new String[]{}, 
+				buffer.toString(), 
+				"",
+				"",
+				false);
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
index f0b3bd4..aa2de45 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contributions for
@@ -7341,6 +7345,7 @@
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=421711, [1.8][compiler] '_' as identifier for a lambda parameter should be rejected.
 public void testUnderScoreParameter() {
+		String level = this.complianceLevel >= ClassFileConstants.JDK9 ? "ERROR" : "WARNING";
 		this.runNegativeTest(
 			new String[] {
 					"X.java", 
@@ -7361,7 +7366,7 @@
 			"	           ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
 			"----------\n" + 
-			"2. WARNING in X.java (at line 8)\n" + 
+			"2. "+ level +" in X.java (at line 8)\n" + 
 			"	F f2 = _ -> {};\n" + 
 			"	       ^\n" + 
 			"\'_\' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
index 434ea2c..27107a8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -329,138 +333,159 @@
 	}
 	public void testImportUnresolved_fatal() {
 		Map<String,String> options = getCompilerOptions();
-		options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
-		options.put(JavaCore.COMPILER_PB_FATAL_OPTIONAL_ERROR, JavaCore.ENABLED);
-		runNegativeTest(
-			true, // flush dir
-			new String[] {
-				"p/Z.java",
-				"package p;\n" +
-				"public class Z {\n" +
-				"	public static void main(String[] args) throws Exception {\n" +
-				"		try {\n" +
-				"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
-				"		} catch (java.lang.Error e) {\n" +
-				"			System.err.println(e.getMessage());\n" +
-				"		}\n" +
-				"	}\n" +
-				"}\n",
-				"X.java",
-				"import com.bogus.Missing;\n" +
-				"public class X {\n" +
-				"	public static void main(String[] args) {\n" +
-				"		new X().test();\n" +
-				"	}\n" +
-				"	void test() {\n" +
-				"		System.out.println(\"OK\");\n" +
-				"	}\n" +
-				"}\n"
-			},
-			null, // libs
-			options,
-			"----------\n" + 
-			"1. ERROR in X.java (at line 1)\n" + 
-			"	import com.bogus.Missing;\n" + 
-			"	       ^^^^^^^^^\n" + 
-			"The import com.bogus cannot be resolved\n" + 
-			"----------\n",
-			"",
-			"Unresolved compilation problem: \n" + 
-			"	The import com.bogus cannot be resolved",
-			JavacTestOptions.SKIP);
+		try {
+			options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
+			options.put(JavaCore.COMPILER_PB_FATAL_OPTIONAL_ERROR, JavaCore.ENABLED);
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
+			runNegativeTest(
+					true, // flush dir
+					new String[] {
+							"p/Z.java",
+							"package p;\n" +
+									"public class Z {\n" +
+									"	public static void main(String[] args) throws Exception {\n" +
+									"		try {\n" +
+									"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+									"		} catch (java.lang.Error e) {\n" +
+									"			System.err.println(e.getMessage());\n" +
+									"		}\n" +
+									"	}\n" +
+									"}\n",
+									"X.java",
+									"import com.bogus.Missing;\n" +
+											"public class X {\n" +
+											"	public static void main(String[] args) {\n" +
+											"		new X().test();\n" +
+											"	}\n" +
+											"	void test() {\n" +
+											"		System.out.println(\"OK\");\n" +
+											"	}\n" +
+											"}\n"
+					},
+					null, // libs
+					options,
+					"----------\n" + 
+							"1. ERROR in X.java (at line 1)\n" + 
+							"	import com.bogus.Missing;\n" + 
+							"	       ^^^^^^^^^\n" + 
+							"The import com.bogus cannot be resolved\n" + 
+							"----------\n",
+							"",
+							"Unresolved compilation problem: \n" + 
+									"	The import com.bogus cannot be resolved",
+									JavacTestOptions.SKIP);
+		} finally {
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		}
 	}
 	public void testPackageConflict() {
-		runNegativeTest(
-			true, // flush dir
-			new String[] {
-				"p/z.java",
-				"package p;\n" +
-				"public class z {\n" +
-				"	public static void main(String[] args) throws Exception {\n" +
-				"		try {\n" +
-				"			Class.forName(\"p.z.X\").newInstance();\n" +
-				"		} catch (ClassNotFoundException e) {\n" +
-				"			System.out.println(e.getClass().getName());\n" +
-				"		}\n" +
-				"	}\n" +
-				"}\n",
-				"p/z/X.java",
-				"package p.z;\n" +
-				"public class X {\n" +
-				"	public X() {\n" +
-				"		System.out.println(\"OK\");\n" +
-				"	}\n" +
-				"}\n",
-			},
-			null, // libs
-			getCompilerOptions(),
-			"----------\n" + 
-			"1. ERROR in p\\z\\X.java (at line 1)\n" + 
-			"	package p.z;\n" + 
-			"	        ^^^\n" + 
-			"The package p.z collides with a type\n" + 
-			"----------\n",
-			"java.lang.ClassNotFoundException", // cannot generate code in presence of the above error
-			"",
-			JavacTestOptions.SKIP);
+		Map<String,String> options = getCompilerOptions();
+		try {
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
+
+			runNegativeTest(
+					true, // flush dir
+					new String[] {
+							"p/z.java",
+							"package p;\n" +
+									"public class z {\n" +
+									"	public static void main(String[] args) throws Exception {\n" +
+									"		try {\n" +
+									"			Class.forName(\"p.z.X\").newInstance();\n" +
+									"		} catch (ClassNotFoundException e) {\n" +
+									"			System.out.println(e.getClass().getName());\n" +
+									"		}\n" +
+									"	}\n" +
+									"}\n",
+									"p/z/X.java",
+									"package p.z;\n" +
+											"public class X {\n" +
+											"	public X() {\n" +
+											"		System.out.println(\"OK\");\n" +
+											"	}\n" +
+											"}\n",
+					},
+					null, // libs
+					options,
+					"----------\n" + 
+							"1. ERROR in p\\z\\X.java (at line 1)\n" + 
+							"	package p.z;\n" + 
+							"	        ^^^\n" + 
+							"The package p.z collides with a type\n" + 
+							"----------\n",
+							"java.lang.ClassNotFoundException", // cannot generate code in presence of the above error
+							"",
+							JavacTestOptions.SKIP);
+		} finally {
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		}
 	}
 	public void testImportVariousProblems() {
-		runNegativeTest(
-			true, // flush dir
-			new String[] {
-				"p/Z.java",
-				"package p;\n" +
-				"public class Z {\n" +
-				"	public static void main(String[] args) throws Exception {\n" +
-				"		try {\n" +
-				"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
-				"		} catch (ClassNotFoundException e) {\n" +
-				"			System.out.println(e.getClass().getName());\n" +
-				"		}\n" +
-				"	}\n" +
-				"}\n",
-				"p1/Y.java",
-				"package p1;\n" +
-				"public class Y {}\n",
-				"p2/Y.java",
-				"package p2;\n" +
-				"public class Y {}\n",
-				"X.java",
-				"import java.util;\n" +
-				"import p.Z;\n" +
-				"import p1.Y;\n" +
-				"import p2.Y;\n" +
-				"public class X {\n" +
-				"	public X() {\n" +
-				"		System.out.println(\"OK\");\n" +
-				"	}\n" +
-				"}\n" +
-				"class Z {}\n"
-			},
-			null, // libs
-			getCompilerOptions(),
-			"----------\n" + 
-			"1. ERROR in X.java (at line 1)\n" + 
-			"	import java.util;\n" + 
-			"	       ^^^^^^^^^\n" + 
-			"Only a type can be imported. java.util resolves to a package\n" + 
-			"----------\n" + 
-			"2. ERROR in X.java (at line 2)\n" + 
-			"	import p.Z;\n" + 
-			"	       ^^^\n" + 
-			"The import p.Z conflicts with a type defined in the same file\n" + 
-			"----------\n" + 
-			"3. ERROR in X.java (at line 4)\n" + 
-			"	import p2.Y;\n" + 
-			"	       ^^^^\n" + 
-			"The import p2.Y collides with another import statement\n" + 
-			"----------\n",
-			"OK",
-			"",
-			JavacTestOptions.SKIP);
+		Map<String,String> options = getCompilerOptions();
+		try {
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
+
+			runNegativeTest(
+					true, // flush dir
+					new String[] {
+							"p/Z.java",
+							"package p;\n" +
+									"public class Z {\n" +
+									"	public static void main(String[] args) throws Exception {\n" +
+									"		try {\n" +
+									"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+									"		} catch (ClassNotFoundException e) {\n" +
+									"			System.out.println(e.getClass().getName());\n" +
+									"		}\n" +
+									"	}\n" +
+									"}\n",
+									"p1/Y.java",
+									"package p1;\n" +
+											"public class Y {}\n",
+											"p2/Y.java",
+											"package p2;\n" +
+													"public class Y {}\n",
+													"X.java",
+													"import java.util;\n" +
+															"import p.Z;\n" +
+															"import p1.Y;\n" +
+															"import p2.Y;\n" +
+															"public class X {\n" +
+															"	public X() {\n" +
+															"		System.out.println(\"OK\");\n" +
+															"	}\n" +
+															"}\n" +
+															"class Z {}\n"
+					},
+					null, // libs
+					options,
+					"----------\n" + 
+							"1. ERROR in X.java (at line 1)\n" + 
+							"	import java.util;\n" + 
+							"	       ^^^^^^^^^\n" + 
+							"Only a type can be imported. java.util resolves to a package\n" + 
+							"----------\n" + 
+							"2. ERROR in X.java (at line 2)\n" + 
+							"	import p.Z;\n" + 
+							"	       ^^^\n" + 
+							"The import p.Z conflicts with a type defined in the same file\n" + 
+							"----------\n" + 
+							"3. ERROR in X.java (at line 4)\n" + 
+							"	import p2.Y;\n" + 
+							"	       ^^^^\n" + 
+							"The import p2.Y collides with another import statement\n" + 
+							"----------\n",
+							"OK",
+							"",
+							JavacTestOptions.SKIP);
+		} finally {
+			options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+		}
 	}
 	public void testImportStaticProblems() {
 		if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses static imports
+		Map<String,String> options = getCompilerOptions();
+		options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 		runNegativeTest(
 			true, // flush dir
 			new String[] {
@@ -491,7 +516,7 @@
 				"class Z {}\n"
 			},
 			null, // libs
-			getCompilerOptions(),
+			options,
 			"----------\n" + 
 			"1. ERROR in X.java (at line 1)\n" + 
 			"	import static p1.Y;\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index 96bbce4..35c595e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Stephan Herrmann - initial API and implementation
  *     Till Brychcy <register.eclipse@brychcy.de> - Contribution for
@@ -8122,6 +8126,8 @@
 }
 public void testBug462790() {
 	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // multi catch used
+	Map<String,String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"EclipseBug.java",
@@ -8141,7 +8147,7 @@
 			"	}\n" + 
 			"}"
 		},
-		getCompilerOptions(),
+		options,
 		"----------\n" + 
 		"1. WARNING in EclipseBug.java (at line 5)\n" + 
 		"	String command = (String)getCommand(commandType);\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index aecc09f..69f7dd1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2014 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
@@ -11944,7 +11948,7 @@
 			"        }\n" +
 			"    }\n" +
 			"    private static Number getNumber() {\n" +
-			"        return new Double(Math.sqrt(-1));\n" +
+			"        return Double.valueOf(Math.sqrt(-1));\n" +
 			"    }\n" +
 			"}\n"},
 		"----------\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index 30e7c01..8a2379f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Stephan Herrmann - initial API and implementation
  *     IBM Corporation
@@ -5094,6 +5098,8 @@
 
 //apply null default to return type - annotation at method:
 public void testDefault03_bin() {
+	Map<String,String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"X.java",
@@ -5105,7 +5111,7 @@
 			"	}\n" +
 			"}\n"
 		},
-		getCompilerOptions(),
+		options,
 		"");
 	runConformTestWithLibs(
 		new String[] {
@@ -5117,12 +5123,14 @@
 			"	}\n" +
 			"}\n"
 		},
-		getCompilerOptions(),
+		options,
 		"");
 }
 
 // apply null default to field - also test mixing of explicit annotation with default @NonNull (other annot is not rendered in error)
 public void testDefault04_bin() {
+	Map<String,String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"X.java",
@@ -5131,10 +5139,10 @@
 			"@Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.CLASS) @interface Important {}\n" +
 			"@NonNullByDefault(DefaultLocation.FIELD)\n" +
 			"public class X {\n" +
-			"	@Important Number field = new Double(1.1d);\n" +
+			"	@Important Number field = new Double(1.1);\n" +
 			"}\n"
 		},
-		getCompilerOptions(),
+		options,
 		"");
 	runNegativeTestWithLibs(
 		new String[] {
@@ -5155,6 +5163,8 @@
 
 // default default
 public void testDefault05_bin() {
+	Map<String,String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"X.java",
@@ -5167,7 +5177,7 @@
 			"	}\n" +
 			"}\n"
 		},
-		getCompilerOptions(),
+		options,
 		"");
 	runNegativeTestWithLibs(
 		new String[] {
@@ -7315,7 +7325,7 @@
 			"interface Baz extends Foo<Integer, Integer> {}\n" + 
 			"\n" +
 			"class Impl implements Baz {\n" + 
-			"  public Integer m(Integer i) { return new Integer(0); }\n" + 
+			"  public Integer m(Integer i) { return Integer.valueOf(0); }\n" + 
 			"}\n" +
 			"\n" + 
 			"public class Test {\n" + 
@@ -7324,7 +7334,7 @@
 		},
 		"----------\n" + 
 		"1. ERROR in Test.java (at line 11)\n" + 
-		"	public Integer m(Integer i) { return new Integer(0); }\n" + 
+		"	public Integer m(Integer i) { return Integer.valueOf(0); }\n" + 
 		"	       ^^^^^^^\n" + 
 		"The return type is incompatible with \'@NonNull Integer\' returned from Foo<Integer,Integer>.m(Integer) (mismatching null constraints)\n" + 
 		"----------\n" + 
@@ -9013,6 +9023,7 @@
 public void testBug477719() {
 	Map compilerOptions = getCompilerOptions();
 	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
+	compilerOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"X.java",
@@ -12396,6 +12407,7 @@
 		""
 	);
 }
+
 public void testBug496591() {
 	runConformTestWithLibs(
 		new String[] {
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 df97b0c..21fdcd1 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
@@ -4,6 +4,9 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  *
  * Contributors:
  *     Sven Strohschein - initial API and implementation
@@ -12,6 +15,7 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
@@ -35,7 +39,7 @@
 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(true);
 
 		PackageBinding packageBinding = new PackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
-		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray());
+		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null);
 		assertNotNull(resultBinding);
 
 		assertTrue(nameEnv.isPackageSearchExecuted);
@@ -51,7 +55,7 @@
 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(false);
 
 		PackageBinding packageBinding = new PackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
-		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray());
+		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), null);
 		assertNull(resultBinding); // (not implemented)
 
 		assertTrue(nameEnv.isPackageSearchExecuted);
@@ -135,11 +139,6 @@
 		}
 
 		@Override
-		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
-			return null;
-		}
-
-		@Override
 		public boolean isPackage(char[][] parentPackageName, char[] packageName) {
 			return false;
 		}
@@ -153,10 +152,16 @@
 		}
 
 		@Override
-		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) {
+		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, IModuleContext context) {
 			this.isTypeSearchExecutedWithSearchWithSecondaryTypes = true;
 			this.isTypeSearchWithSearchWithSecondaryTypes = searchWithSecondaryTypes;
 			return null;
 		}
+
+		@Override
+		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+			// TODO Auto-generated method stub
+			return null;
+		}
 	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java
index 8d35a0e..fa2127d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java
@@ -877,6 +877,7 @@
 		this.runConformTest(
 			new String[] {
 				"X.java",
+				"import java.lang.annotation.Annotation;\n" +
 				"import java.lang.annotation.Repeatable;\n" +
 				"import java.lang.annotation.Retention;\n" +
 				"import static java.lang.annotation.RetentionPolicy.*;\n" +
@@ -895,10 +896,17 @@
 				"  @Attr(1) class Y1 {}\n" +
 				"  @Attr(1) @Attr(2) class Y2 {} \n" +
 				"  public static void main(String args[]) {\n" +
-				"  	System.out.println(\"Y1: \" + Y1.class.getAnnotation(Attr.class));\n" +
-				"  	System.out.println(\"Y2: \" + Y2.class.getAnnotation(Attr.class));\n" +
-				"  	System.out.println(\"Y1: \" + Y1.class.getAnnotation(AttrContainer.class));\n" +
-				"  	System.out.println(\"Y2: \" + Y2.class.getAnnotation(AttrContainer.class));\n" +
+				"  	System.out.print(\"Y1: \" + normalizeAnnotation(Y1.class.getAnnotation(Attr.class)) + \"\\n\");\n" +
+				"  	System.out.print(\"Y2: \" + normalizeAnnotation(Y2.class.getAnnotation(Attr.class)) + \"\\n\");\n" +
+				"  	System.out.print(\"Y1: \" + normalizeAnnotation(Y1.class.getAnnotation(AttrContainer.class)) + \"\\n\");\n" +
+				"  	System.out.print(\"Y2: \" + normalizeAnnotation(Y2.class.getAnnotation(AttrContainer.class)) + \"\\n\");\n" +
+				"  }\n" +
+				"  static String normalizeAnnotation(Annotation a) {\n" +
+				" 		if (a == null) return null;\n" +
+				"	  String str = a.toString();\n" +
+				"	  str = str.replace(\"value={@\", \"value=[@\");\n" +
+				"	  str = str.replace(\")}\", \")]\");\n" +
+				"	  return str;\n" +
 				"  }\n" +
 				"}"
 			},
@@ -1085,12 +1093,19 @@
 				"			  if (annotations.length == 0 || (annotations.length == 1 && annotations[0] == null)) continue;\n" +
 				"			  System.out.print(name + (j == 0 ? \".getAnnotation(\" : \".getAnnotationByType(\") + annotation.getName() + \".class): \");\n" +
 				"			  for (Annotation a : annotations) {\n" +
-				"				  System.out.print(a + \" \");\n" +
+				"				  System.out.print(normalizeAnnotation(a) + \" \");\n" +
 				"			  }\n" +
-				"			  System.out.println();\n" +
+				"			  System.out.print(\"\\n\");\n" +
 				"		  }\n" +
 				"	  }\n" +
 				"  }\n" +
+				"  static String normalizeAnnotation(Annotation a) {\n" +
+				" 		if (a == null) return null;\n" +
+				"	  String str = a.toString();\n" +
+				"	  str = str.replace(\"value={@\", \"value=[@\");\n" +
+				"	  str = str.replace(\")}\", \")]\");\n" +
+				"	  return str;\n" +
+				"  }\n" +
 				"}\n"
 
 			},
@@ -1224,12 +1239,19 @@
 				"			  if (annotations.length == 0 || (annotations.length == 1 && annotations[0] == null)) continue;\n" +
 				"			  System.out.print(name + (j == 0 ? \".getAnnotation(\" : \".getAnnotationByType(\") + annotation.getName() + \".class): \");\n" +
 				"			  for (Annotation a : annotations) {\n" +
-				"				  System.out.print(a + \" \");\n" +
+				"				  System.out.print(normalizeAnnotation(a) + \" \");\n" +
 				"			  }\n" +
-				"			  System.out.println();\n" +
+				"			  System.out.print(\"\\n\");\n" +
 				"		  }\n" +
 				"	  }\n" +
 				"  }\n" +
+				"  static String normalizeAnnotation(Annotation a) {\n" +
+				" 		if (a == null) return null;\n" +
+				"	  String str = a.toString();\n" +
+				"	  str = str.replace(\"value={@\", \"value=[@\");\n" +
+				"	  str = str.replace(\")}\", \")]\");\n" +
+				"	  return str;\n" +
+				"  }\n" +
 				"}\n"
 
 			},
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerialVersionUIDTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerialVersionUIDTests.java
index 87a2c73..70c1374 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerialVersionUIDTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerialVersionUIDTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2014 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -166,7 +170,7 @@
 	);
 }
 //https://bugs.eclipse.org/bugs/show_bug.cgi?id=285124
-public void test008() {
+public void _test008() {
 	this.runConformTest(
 			new String[] {
 				"X.java",
@@ -178,7 +182,7 @@
 		);
 }
 //https://bugs.eclipse.org/bugs/show_bug.cgi?id=285124
-public void test009() {
+public void _test009() {
 	this.runConformTest(
 			new String[] {
 				"X.java",
@@ -193,7 +197,7 @@
 		);
 }
 //https://bugs.eclipse.org/bugs/show_bug.cgi?id=285124
-public void test010() {
+public void _test010() {
 	this.runConformTest(
 			new String[] {
 				"X.java",
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java
index 52db099..ffad3d8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2014 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for bug 374605 - Unreasonable warning for enum-based switch statements
@@ -1056,7 +1060,7 @@
 			"        switch(Days.Sunday) {\n" +
 			"            case \"Sunday\": break;\n" +
 			"        }\n" +
-			"        switch (new Integer(argv.length)) {\n" +
+			"        switch (Integer.valueOf(argv.length)) {\n" +
 			"            case \"0\": break;\n" +
 			"        }\n" +
 			"    }\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index 0680c16..f4f9bc8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -153,6 +157,12 @@
 	since_1_8.add(Unicode18Test.class);
 	since_1_8.add(LambdaShapeTests.class);
 
+	ArrayList since_9 = new ArrayList();
+	since_9.add(Unicode9Test.class);
+	since_9.add(ModuleCompilationTests.class);
+	since_9.add(GenericsRegressionTest_9.class);
+	since_9.add(InterfaceMethodsTest_9.class);
+	
 	// Build final test suite
 	TestSuite all = new TestSuite(TestAll.class.getName());
 	all.addTest(new TestSuite(StandAloneASTParserTest.class));
@@ -208,6 +218,22 @@
 		TestCase.resetForgottenFilters(tests_1_8);
 		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.JDK1_8, tests_1_8));
 	}
+	if ((possibleComplianceLevels & AbstractCompilerTest.F_9) != 0) {
+		ArrayList tests_9 = (ArrayList)standardTests.clone();
+		tests_9.addAll(since_1_4);
+		tests_9.addAll(since_1_5);
+		tests_9.addAll(since_1_6);
+		tests_9.addAll(since_1_7);
+		tests_9.addAll(since_1_8);
+		tests_9.addAll(since_9);
+		// Reset forgotten subsets tests
+		TestCase.TESTS_PREFIX = null;
+		TestCase.TESTS_NAMES = null;
+		TestCase.TESTS_NUMBERS= null;
+		TestCase.TESTS_RANGE = null;
+		TestCase.RUN_ONLY_ID = null;
+		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.JDK9, tests_9));
+	}
 	all.addTest(new TestSuite(Jsr14Test.class));
 	return all;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement17Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement17Test.java
index c1d9a36..e0ce657 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement17Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement17Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2003, 2014 IBM Corporation and others.
+ * Copyright (c) 2003, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
 import junit.framework.Test;
 @SuppressWarnings({ "rawtypes" })
 public class TryStatement17Test extends AbstractRegressionTest {
@@ -1261,6 +1263,61 @@
 			"}\n"
 		});
 }
+public void testBug488569_001() {
+	if (this.complianceLevel < ClassFileConstants.JDK9) {
+		this.runNegativeTest(
+			new String[] {
+					"X.java",
+					"public class X {\n" +
+					"    public static void main(String [] args) throws Exception {\n" +
+					"    	Z z1 = new Z();\n" +
+					"        try (Y y1 = new Y(); z1;) {\n" +
+					"        }  \n" +
+					"    }  \n" +
+					"}\n" +
+					"class Y implements AutoCloseable {\n" +
+					"	public void close() throws Exception {\n" +
+					"	}\n" +
+					"}\n" +
+					"\n" +
+					"class Z implements AutoCloseable {\n" +
+					"	public void close() throws Exception {\n" +
+					"	}   \n" +
+					"}\n" +
+					"\n"
+			},
+			"----------\n" + 
+			"1. ERROR in X.java (at line 4)\n" + 
+			"	try (Y y1 = new Y(); z1;) {\n" + 
+			"	                     ^^\n" + 
+			"Variable resource not allowed here for source level below 9\n" + 
+			"----------\n");
+	} else {
+		this.runConformTest(
+			new String[] {
+				"X.java",
+				"public class X {\n" +
+				"    public static void main(String [] args) throws Exception {\n" +
+				"    	Z z1 = new Z();\n" +
+				"        try (Y y1 = new Y(); z1;) {\n" +
+				"        }  \n" +
+				"    }  \n" +
+				"}\n" +
+				"class Y implements AutoCloseable {\n" +
+				"	public void close() throws Exception {\n" +
+				"	}\n" +
+				"}\n" +
+				"\n" +
+				"class Z implements AutoCloseable {\n" +
+				"	public void close() throws Exception {\n" +
+				"	}   \n" +
+				"}\n" +
+				"\n"
+			}, 
+			"");
+
+	}
+}
 
 public static Class testClass() {
 	return TryStatement17Test.class;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java
new file mode 100644
index 0000000..1d59695
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java
@@ -0,0 +1,719 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import junit.framework.Test;
+@SuppressWarnings({ "rawtypes" })
+public class TryStatement9Test extends AbstractRegressionTest {
+
+static {
+///	TESTS_NAMES = new String[] { "testBug488569_019" };
+//	TESTS_NUMBERS = new int[] { 40, 41, 43, 45, 63, 64 };
+//	TESTS_RANGE = new int[] { 11, -1 };
+}
+public TryStatement9Test(String name) {
+	super(name);
+}
+public static Test suite() {
+	return buildMinimalComplianceTestSuite(testClass(), F_9);
+}
+
+public void testBug488569_001() { // vanilla test case
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.Closeable;\n" +
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Y implements Closeable {\n" +
+				"        @Override\n" +
+				"        public void close() throws IOException {\n" +
+				"                // nothing\n" +
+				"        }\n" +
+				"}\n" +
+				"public class X {\n" +
+				"\n" +
+				"        public void foo() throws IOException {\n" +
+				"             final Y y1 = new Y();\n" +
+				"             try (y1) { \n" +
+				"            	 //\n" +
+				"             }\n" +
+				"        } \n" +
+				"        public static void main(String[] args) {\n" +
+				"			System.out.println(\"Done\");\n" +
+				"		}\n" +
+				"} \n"
+			}, 
+			"Done");
+}
+
+// vanilla with a delimiter
+public void testBug488569_002() { 
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.Closeable;\n" +
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Y implements Closeable {\n" +
+				"        @Override\n" +
+				"        public void close() throws IOException {\n" +
+				"                // nothing\n" +
+				"        }\n" +
+				"}\n" +
+				"public class X {\n" +
+				"\n" +
+				"        public void foo() throws IOException {\n" +
+				"             final Y y1 = new Y();\n" +
+				"             try (y1;) { \n" +
+				"            	 //\n" +
+				"             }\n" +
+				"        } \n" +
+				"        public static void main(String[] args) {\n" +
+				"			System.out.println(\"Done\");\n" +
+				"		}\n" +
+				"} \n"
+			}, 
+			"Done");
+}
+
+public void testBug488569_003() { 
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.Closeable;\n" +
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Y implements Closeable {\n" +
+				"        @Override\n" +
+				"        public void close() throws IOException {\n" +
+				"                // nothing\n" +
+				"        }\n" +
+				"}\n" +
+				"public class X {\n" +
+				"\n" +
+				"        public void foo() throws IOException {\n" +
+				"             final Y y1 = new Y();\n" +
+				"             final Y y2 = new Y();\n" +
+				"             try (y1; y2) { \n" +
+				"            	 //\n" +
+				"             }\n" +
+				"        } \n" +
+				"        public static void main(String[] args) {\n" +
+				"			System.out.println(\"Done\");\n" +
+				"		}\n" +
+				"} \n"
+			}, 
+			"Done");
+}
+public void testBug488569_004() { 
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.Closeable;\n" +
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Y implements Closeable {\n" +
+				"        @Override\n" +
+				"        public void close() throws IOException {\n" +
+				"                // nothing\n" +
+				"        }\n" +
+				"}\n" +
+				"public class X {\n" +
+				"\n" +
+				"        public void foo() throws IOException {\n" +
+				"             final Y y1 = new Y();\n" +
+				"             try (y1; final Y y2 = new Y()) { \n" +
+				"            	 //\n" +
+				"             }\n" +
+				"        } \n" +
+				"        public static void main(String[] args) {\n" +
+				"			System.out.println(\"Done\");\n" +
+				"		}\n" +
+				"} \n"
+			}, 
+		"Done");
+}
+
+public void testBug488569_005() { 
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.Closeable;\n" +
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Y implements Closeable {\n" +
+				"        @Override\n" +
+				"        public void close() throws IOException {\n" +
+				"                // nothing\n" +
+				"        }\n" +
+				"}\n" +
+				"public class X {\n" +
+				"\n" +
+				"        public void foo() throws IOException {\n" +
+				"             final Y y1 = new Y();\n" +
+				"             try (final Y y = new Y(); y1; final Y y2 = new Y()) { \n" +
+				"            	 //\n" +
+				"             }\n" +
+				"        } \n" +
+				"        public static void main(String[] args) {\n" +
+				"			System.out.println(\"Done\");\n" +
+				"		}\n" +
+				"} \n"
+			}, 
+		"Done");
+}
+public void testBug488569_006() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"public class X { \n" +
+			"    public void foo() throws IOException {\n" +
+			"         Y y1 = new Y();\n" +
+			"         try(y1) { \n" +
+			"             return;\n" +
+			"         }\n" +
+			"    } \n" +
+			"}  \n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"		final int x = 10;\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}",
+		},
+		"");
+}
+
+// check for the error for non-effectively final variable.
+public void testBug488569_007() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             Y y1 = new Y();\n" +
+			"             y1 = new Y();\n" +
+			"             try (y1) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 15)\n" + 
+		"	try (y1) { \n" + 
+		"	     ^^\n" + 
+		"Local variable y1 defined in an enclosing scope must be final or effectively final\n" + 
+		"----------\n");
+}
+//check for the error for combination of NameRef and LocalVarDecl.
+public void testBug488569_008() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             try (y1; Y y1 = new Y()) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 13)\n" + 
+		"	try (y1; Y y1 = new Y()) { \n" + 
+		"	     ^^\n" + 
+		"y1 cannot be resolved\n" + 
+		"----------\n");
+}
+
+//check for the warning for combination of LocalVarDecl and NameRef.
+public void testBug488569_009() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             try (Y y1 = new Y(); y1) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 13)\n" + 
+		"	try (Y y1 = new Y(); y1) { \n" + 
+		"	                     ^^\n" + 
+		"Duplicate resource reference y1\n" + 
+		"----------\n");
+}
+//check for the warning for combination of NameRef and NameRef.
+public void testBug488569_010() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             Y y1 = new Y();\n" +
+			"             try (y1; y1) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 14)\n" + 
+		"	try (y1; y1) { \n" + 
+		"	         ^^\n" + 
+		"Duplicate resource reference y1\n" + 
+		"----------\n");
+}
+public void testBug488569_011() {
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             try (Y y1 = new Y();y1) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"} \n"
+			}, 
+			"Done");
+}
+
+public void testBug488569_012() {
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"import java.io.Closeable;\n" +
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Y implements Closeable {\n" +
+			"        @Override\n" +
+			"        public void close() throws IOException {\n" +
+			"                // nothing\n" +
+			"        }\n" +
+			"}\n" +
+			"public class X {\n" +
+			"\n" +
+			"        public void foo() throws IOException {\n" +
+			"             Y y = new Y();\n" +
+			"             try (Y y1 = new Y();y;y1) { \n" +
+			"            	 //\n" +
+			"             }\n" +
+			"        } \n" +
+			"        public static void main(String[] args) {\n" +
+			"			System.out.println(\"Done\");\n" +
+			"		}\n" +
+			"} \n"
+			}, 
+			"Done");
+}
+
+// Confirm the behavior as described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=338402#c16 even with the
+// presence of a duplicate variable in-line with javac9.
+public void testBug488569_013() {
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"public class X {\n" +
+			"    public static void main(String [] args) throws Exception {\n" +
+			"    	Z z1 = new Z();\n" +
+			"        try (Y y = new Y();z1;y) {\n" +
+			"        }\n" +
+			"    }  \n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	public void close() throws Exception {\n" +
+			"		System.out.println(\"Y CLOSE\");\n" +
+			"	}\n" +
+			"}\n" +
+			"\n" +
+			"class Z implements AutoCloseable {\n" +
+			"	public void close() throws Exception {\n" +
+			"		System.out.println(\"Z CLOSE\");\n" +
+			"	}\n" +
+			"}\n"
+			}, 
+			"Y CLOSE\n" +
+			"Z CLOSE\n" +
+			"Y CLOSE"
+			);
+}
+
+// check for unhandled-exception error
+public void testBug488569_014() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"public class X {\n" +
+			"	public static void main(String[] args) {\n" +
+			"		Y y1 = new Y();		 		 \n" +
+			"		try (y1)  {\n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} finally {\n" +
+			"		}\n" +
+			"	}\n" +
+			"}\n" +
+			"   \n" +
+			"class Y implements AutoCloseable {\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	}\n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 6)\n" + 
+		"	try (y1)  {\n" + 
+		"	     ^^\n" + 
+		"Unhandled exception type IOException thrown by automatic close() invocation on y1\n" + 
+		"----------\n");
+}
+
+// field to be legal
+public void testBug488569_015(){
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"public class X {\n" +
+			"	final Y y = new Y();\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"	public void foo() {\n" +
+			"		try (y)  {\n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {\n" +
+			"			e.printStackTrace();\n" +
+			"		}\n" +
+			"		finally {  \n" +
+			"		}  \n" +
+			"		//y1 = new Y();	 \n" +
+			"	} \n" +
+			"} \n" +
+			"   \n" +
+			"class Y implements AutoCloseable {\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	}\n" +
+			"}\n"
+			}, 
+			"In Try\n" + 
+			"Closed"
+			);
+}
+//field to be legal - but null field not to be called for close
+public void testBug488569_016(){
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"public class X {\n" +
+			"	final Y y = null;\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"	public void foo() {\n" +
+			"		try (y)  {\n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {\n" +
+			"			e.printStackTrace();\n" +
+			"		}\n" +
+			"		finally {  \n" +
+			"		}  \n" +
+			"	} \n" +
+			"} \n" +
+			"   \n" +
+			"class Y implements AutoCloseable {\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	}\n" +
+			"}\n"
+			}, 
+			"In Try" 
+			);
+}
+
+// field in various avatars
+public void testBug488569_017(){
+	this.runConformTest(
+			new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Z {\n" +
+			"	final Y yz = new Y();\n" +
+			"}\n" +
+			"public class X extends Z {\n" +
+			"	final Y y2 = new Y();\n" +
+			"	\n" +
+			"	public void foo() {\n" +
+			"		try (super.yz; y2)  {\n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {\n" +
+			"			\n" +
+			"		}finally { \n" +
+			"		}\n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	@Override\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	} \n" +
+			"}  \n" 
+			}, 
+			"In Try\n" + 
+			"Closed\n" + 
+			"Closed"
+			);
+}
+
+// negative tests: non-final fields
+public void testBug488569_018() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Z {\n" +
+			"	 Y yz = new Y();\n" +
+			"}\n" +
+			"public class X extends Z {\n" +
+			"	 Y y2 = new Y();\n" +
+			"	\n" +
+			"	public void foo() {\n" +
+			"		try (this.y2; super.yz;y2)  {  \n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {			  \n" +
+			"		}\n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	@Override\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	} \n" +
+			"}",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 10)\n" + 
+		"	try (this.y2; super.yz;y2)  {  \n" + 
+		"	          ^^\n" + 
+		"Field y2 must be final\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 10)\n" + 
+		"	try (this.y2; super.yz;y2)  {  \n" + 
+		"	                    ^^\n" + 
+		"Field yz must be final\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 10)\n" + 
+		"	try (this.y2; super.yz;y2)  {  \n" + 
+		"	                       ^^\n" + 
+		"Local variable y2 defined in an enclosing scope must be final or effectively final\n" + 
+		"----------\n");
+}
+//negative tests: duplicate fields
+public void testBug488569_019() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Z {\n" +
+			"	 final Y yz = new Y();\n" +
+			"}\n" +
+			"public class X extends Z {\n" +
+			"	final  Y y2 = new Y();\n" +
+			"	\n" +
+			"	 Y bar() {\n" +
+			"		 return new Y();\n" +
+			"	 }\n" +
+			"	public void foo() {\n" +
+			"		Y y3 = new Y();\n" +
+			"		try (y3; y3;super.yz;super.yz;this.y2;)  {  \n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {			  \n" +
+			"		} \n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	@Override\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	}  \n" +
+			"}  \n",
+		},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 14)\n" + 
+		"	try (y3; y3;super.yz;super.yz;this.y2;)  {  \n" + 
+		"	         ^^\n" + 
+		"Duplicate resource reference y3\n" + 
+		"----------\n" + 
+		"2. WARNING in X.java (at line 14)\n" + 
+		"	try (y3; y3;super.yz;super.yz;this.y2;)  {  \n" + 
+		"	                     ^^^^^^^^\n" + 
+		"Duplicate resource reference super.yz\n" + 
+		"----------\n");
+}
+
+public void testBug488569_020() { // vanilla test case
+	this.runConformTest(
+			new String[] {
+				"X.java",
+				"import java.io.IOException;\n" +
+				"\n" +
+				"public class X {\n" +
+				"     final Z y2 = new Z();\n" +
+				"     public static void main(String[] args) throws Exception {\n" +
+				"          X t = new X();\n" +
+				"          try (t.y2) {     \n" +
+				"          }          \n" +
+				"     }  \n" +
+				"}\n" +
+				"\n" +
+				"class Z implements AutoCloseable {\n" +
+				"     @Override\n" +
+				"     public void close() throws IOException {\n" +
+				"          System.out.println(\"Done\");\n" +
+				"     }\n" +
+				"} \n"
+			}, 
+			"Done");
+}
+
+//negative tests: duplicate fields
+public void testBug488569_021() {
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"\n" +
+			"public class X {\n" +
+			"     final Z z = new Z();\n" +
+			"     public X() {\n" +
+			"          try(this.z) {\n" +
+			"               \n" +
+			"          }\n" +
+			"     }\n" +
+			"}\n" +
+			"\n" +
+			"class Z implements AutoCloseable {\n" +
+			"     @Override\n" +
+			"     public void close() throws IOException {\n" +
+			"          System.out.println(\"Closed\");\n" +
+			"     } \n" +
+			"}  \n",
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 6)\n" + 
+		"	try(this.z) {\n" + 
+		"	    ^^^^^^\n" + 
+		"Unhandled exception type IOException thrown by automatic close() invocation on z\n" + 
+		"----------\n");
+}
+
+
+public static Class testClass() {
+	return TryStatement9Test.class;
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
index 2fa806a..532520b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
@@ -65,12 +65,12 @@
 		"\n"+
 		// Print type annotations on super types
 		"  public static void printTypeAnnotations(Class<?> clazz) {\n"+
-		"    System.out.println(\"Annotations on superclass of \"+clazz.getName());\n"+
+		"    System.out.print(\"Annotations on superclass of \"+clazz.getName() +\"\\n\");\n"+
 		"    AnnotatedType superat = clazz.getAnnotatedSuperclass();\n"+
 		"    Helper.printAnnos(\"  \", superat.getType(),superat.getAnnotations());\n"+
 		"    AnnotatedType[] superinterfaces = clazz.getAnnotatedInterfaces();\n"+
 		"    if (superinterfaces.length!=0) {\n"+
-		"      System.out.println(\"Annotations on superinterfaces of \"+clazz.getName());\n"+
+		"      System.out.print(\"Annotations on superinterfaces of \"+clazz.getName() +\"\\n\");\n"+
 		"      for (int j=0;j<superinterfaces.length;j++) {\n"+
 		"        Helper.printAnnos(\"  \", superinterfaces[j].getType(),superinterfaces[j].getAnnotations());\n"+
 		"      }\n"+
@@ -89,20 +89,22 @@
 		"      System.out.print(tv.getName());\n"+
 		"      if ((t+1)<tvs.length) System.out.print(\",\");\n"+
 		"    }\n"+
-		"    System.out.println(\">\");\n"+
+		"    System.out.print(\">\\n\");\n"+
 		"  }\n"+
 		"  public static String toStringAnno(Annotation anno) {\n"+
 		"    String s = anno.toString();\n"+
+		"	 s = s.replace(\"\\\"\", \"\");\n" +
+		"	 s = s.replace(\"'\", \"\");\n" +
 		"    if (s.endsWith(\"()\")) return s.substring(0,s.length()-2); else return s;\n"+
 		"  }\n"+
 		"  \n"+
 		"  public static void printAnnos(String header, Type t, Annotation[] annos) {\n"+
-		"    if (annos.length==0) { System.out.println(header+t+\":no annotations\"); return;} \n"+
+		"    if (annos.length==0) { System.out.print(header+t+\":no annotations\\n\"); return;} \n"+
 		"    System.out.print(header+t+\":\");\n"+
 		"    for (int i=0;i<annos.length;i++) {\n"+
 		"      System.out.print(toStringAnno(annos[i])+\" \");\n"+
 		"    }\n"+
-		"    System.out.println();\n"+
+		"    System.out.print(\"\\n\");\n"+
 		"  }\n"+
 		"}\n";
 	
@@ -6616,7 +6618,7 @@
 				"  }\n" + 
 				"}\n"
 			},
-			"@TestAnn1(value=1)");
+			"@TestAnn1(value=" + decorateAnnotationValueLiteral("1") + ")");
 	}
 	public void testBug492322readFromClass() {
 		runConformTest(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Unicode9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Unicode9Test.java
new file mode 100644
index 0000000..7425385
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Unicode9Test.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.Map;
+
+import junit.framework.Test;
+
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+public class Unicode9Test extends AbstractRegressionTest {
+public Unicode9Test(String name) {
+	super(name);
+}
+public static Test suite() {
+	return buildMinimalComplianceTestSuite(testClass(), F_9);
+}
+public void test1() {
+	Map<String, String> options = getCompilerOptions();
+	options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"		public int a\u20BE; // new unicode character in unicode 8.0 \n" + 
+			"}",
+		},
+		"",
+		options);
+}
+public static Class<Unicode9Test> testClass() {
+	return Unicode9Test.class;
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java
index c1cabea..2a96957 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -3736,4 +3740,42 @@
 			},
 			"");
 		}
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=488658
+		public void testBug488658_001() throws Exception {
+			if (this.complianceLevel < ClassFileConstants.JDK9) return;
+			this.runConformTest(
+				new String[] {
+					"X.java",
+					"class Y<T> {}\n"+
+					"@SuppressWarnings(\"unused\")\n" +
+					"public class X {\n"+
+					"	@SafeVarargs\n"+
+					"	private <T> Y<T> foo(T ... a) {\n"+
+					"		return null;\n"+
+					"	}\n"+
+					"}\n",
+				},
+			"");
+			Map options = getCompilerOptions();
+			options.put(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION, JavaCore.ERROR);
+			this.runNegativeTest(
+				new String[] {
+					"X.java",
+					"class Y<T> {}\n"+
+					"public class X {\n"+
+					"@SuppressWarnings(\"unused\")\n" +
+					"	private <T> Y<T> foo(T ... a) {\n"+
+					"		return null;\n"+
+					"	}\n"+
+					"}\n"
+				},
+				"----------\n" + 
+				"1. WARNING in X.java (at line 4)\n" + 
+				"	private <T> Y<T> foo(T ... a) {\n" + 
+				"	                           ^\n" + 
+				"Type safety: Potential heap pollution via varargs parameter a\n" + 
+				"----------\n");
+
+		}
+
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
index d75b500..b074c59 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -53,7 +57,7 @@
 		super(name);
 	}
 	
-	private static final int JLS_LATEST = AST.JLS8;
+	private static final int AST_JLS_LATEST = AST.JLS9;
 
 	public ASTNode runConversion(
 			int astLevel,
@@ -83,7 +87,7 @@
 				"		System.out.println(length);\n" + 
 				"	}\n" + 
 				"}";
-		ASTNode node = runConversion(JLS_LATEST, contents, true, true, true, "p/X.java");
+		ASTNode node = runConversion(AST_JLS_LATEST, contents, true, true, true, "p/X.java");
 		assertTrue("Should be a compilation unit", node instanceof CompilationUnit);
 		CompilationUnit unit = (CompilationUnit) node;
 		List types = unit.types();
@@ -116,7 +120,7 @@
 	}
 
 	public void test2() {
-		ASTParser parser = ASTParser.newParser(JLS_LATEST);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		parser.setEnvironment(null, null, null, true);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -145,7 +149,7 @@
 
 	public void test3() throws IOException {
 		File rootDir = new File(System.getProperty("java.io.tmpdir"));
-		ASTParser parser = ASTParser.newParser(JLS_LATEST);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		parser.setEnvironment(null, null, null, true);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -235,7 +239,7 @@
 	}
 
 	public void test4() {
-		ASTParser parser = ASTParser.newParser(JLS_LATEST);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		try {
 			parser.setEnvironment(null, null, new String[] {"UTF-8"}, true);
 			assertTrue("Should have failed", false);
@@ -245,7 +249,7 @@
 	}
 
 	public void test5() {
-		ASTParser parser = ASTParser.newParser(JLS_LATEST);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		try {
 			parser.setEnvironment(null, new String[] {}, new String[] {"UTF-8"}, true);
 			assertTrue("Should have failed", false);
@@ -256,7 +260,7 @@
 
 	public void test6() throws IOException {
 		File rootDir = new File(System.getProperty("java.io.tmpdir"));
-		ASTParser parser = ASTParser.newParser(JLS_LATEST);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		parser.setEnvironment(null, null, null, true);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -579,7 +583,7 @@
 		}
 
 		try {
-			ASTParser parser = ASTParser.newParser(JLS_LATEST);
+			ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 			parser.setKind(ASTParser.K_COMPILATION_UNIT);
 			parser.setCompilerOptions(JavaCore.getOptions());
 			parser.createASTs(
@@ -602,7 +606,7 @@
 				"}\n";
 		Map<String, String> options = JavaCore.getOptions();
 		JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
 		parser.setCompilerOptions(options);
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setSource(source.toCharArray());
@@ -626,7 +630,7 @@
 				"}\n";
 		Map<String, String> options = JavaCore.getOptions();
 		JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setCompilerOptions(options);
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setSource(source.toCharArray());
@@ -649,7 +653,7 @@
 	 */
 	public void testBug480545() {
 	    String input = "class Test2 { void f(Test2... xs) {} }";
-	    ASTParser parser = ASTParser.newParser(AST.JLS8);
+	    ASTParser parser = ASTParser.newParser(AST.JLS9);
 	    parser.setSource(input.toCharArray());
 	    Map<String, String> options = JavaCore.getOptions();
 	    JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
@@ -662,7 +666,7 @@
                        "    public static final if ËŠ = new if(null, null, null, null);\n"+
                        "  }\n" +
                         "}";	    		
-	    ASTParser parser = ASTParser.newParser(AST.JLS8);
+	    ASTParser parser = ASTParser.newParser(AST.JLS9);
 	    parser.setSource(input.toCharArray());
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
index dc4caa1..07a0527 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java
@@ -403,7 +403,7 @@
 /**
  * Tests code snippet that include a package declaration.
  */
-public void testPackage() {
+public void _testPackage() {
 	if (isJRockitVM()) return;
 	// TBD: Test access to package private member
 	// TBD: Test access to package class and members in another package than a java.* package
@@ -514,7 +514,7 @@
  * Tests the return type for a Boolean object.
  */
 public void testReturnTypeBooleanObject() {
-	evaluateWithExpectedType("return new Boolean(true);".toCharArray(), "java.lang.Boolean".toCharArray());
+	evaluateWithExpectedType("return Boolean.valueOf(true);".toCharArray(), "java.lang.Boolean".toCharArray());
 }
 /**
  * Tests the return type for a char.
@@ -526,7 +526,7 @@
  * Tests the return type for a Character object.
  */
 public void testReturnTypeCharacterObject() {
-	evaluateWithExpectedType("return new Character('c');".toCharArray(), "java.lang.Character".toCharArray());
+	evaluateWithExpectedType("return Character.valueOf('c');".toCharArray(), "java.lang.Character".toCharArray());
 }
 /**
  * Tests the return type for a char array.
@@ -550,7 +550,7 @@
  * Tests the return type for a Double object.
  */
 public void testReturnTypeDoubleObject() {
-	evaluateWithExpectedType("return new Double(1.0);".toCharArray(), "java.lang.Double".toCharArray());
+	evaluateWithExpectedType("return Double.valueOf(1.0);".toCharArray(), "java.lang.Double".toCharArray());
 }
 /**
  * Tests the return type for an empty code snippet.
@@ -574,7 +574,7 @@
  * Tests the return type for a Float object.
  */
 public void testReturnTypeFloatObject() {
-	evaluateWithExpectedType("return new Float(1.0);".toCharArray(), "java.lang.Float".toCharArray());
+	evaluateWithExpectedType("return Float.valueOf(1.0f);".toCharArray(), "java.lang.Float".toCharArray());
 }
 /**
  * Tests the return type for an int.
@@ -586,7 +586,7 @@
  * Tests the return type for an Integer object.
  */
 public void testReturnTypeIntegerObject() {
-	evaluateWithExpectedType("return new Integer(1);".toCharArray(), "java.lang.Integer".toCharArray());
+	evaluateWithExpectedType("return Integer.valueOf(1);".toCharArray(), "java.lang.Integer".toCharArray());
 }
 /**
  * Tests the return type for a long.
@@ -604,7 +604,7 @@
  * Tests the return type for a Long object.
  */
 public void testReturnTypeLongObject() {
-	evaluateWithExpectedType("return new Long(1);".toCharArray(), "java.lang.Long".toCharArray());
+	evaluateWithExpectedType("return Long.valueOf(1);".toCharArray(), "java.lang.Long".toCharArray());
 }
 /**
  * Tests the return type for no explicit returned value.
@@ -640,7 +640,7 @@
  * Tests the return type for a Short object.
  */
 public void testReturnTypeShortObject() {
-	evaluateWithExpectedType("return new Short((short)1);".toCharArray(), "java.lang.Short".toCharArray());
+	evaluateWithExpectedType("return Short.valueOf((short)1);".toCharArray(), "java.lang.Short".toCharArray());
 }
 /**
  * Tests the return type for an int array.
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java
index 2f5a256..2e326d2 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -1536,7 +1536,8 @@
 			"Class c = Class.forName(\"A33\");\n" +
 			"java.lang.reflect.Field field = c.getDeclaredField(\"l\");\n" +
 			"field.setAccessible(true);\n" +
-			"Object o = c.newInstance();\n" +
+			"java.lang.reflect.Constructor constr = c.getConstructor(new Class[] {});\n" +
+			"Object o = constr.newInstance(new Object[]{});\n" +
 			"System.out.println(field.getInt(o));\n" +
 			"} catch(Exception e) {}\n" +
 			"return l;").toCharArray();
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/EvaluationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/EvaluationTest.java
index 5b5631d..cc065cb 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/EvaluationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/EvaluationTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -238,7 +242,7 @@
 		if (displayString == null) {
 			assertTrue("Has value", !result.hasValue());
 		} else {
-			assertTrue("Has value", result.hasValue());
+			assertTrue("Does not have expected value", result.hasValue());
 			assertEquals("Evaluation type", EvaluationResult.T_CODE_SNIPPET, result.getEvaluationType());
 			//assertEquals("Evaluation id", codeSnippet, result.getEvaluationID());
 			assertEquals("Value display string", displayString, result.getValueDisplayString());
@@ -368,7 +372,7 @@
 		if (expectedTypeName == null) {
 			assertTrue("Has value", !result.hasValue());
 		} else {
-			assertTrue("Has value", result.hasValue());
+			assertTrue("Does not have expected value", result.hasValue());
 			assertEquals("Evaluation type", EvaluationResult.T_CODE_SNIPPET, result.getEvaluationType());
 			//assertEquals("Evaluation id", codeSnippet, result.getEvaluationID());
 			assertEquals("Value type name", expectedTypeName, result.getValueTypeName());
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/NegativeCodeSnippetTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/NegativeCodeSnippetTest.java
index d8a0a85..a5c9d05 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/NegativeCodeSnippetTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/NegativeCodeSnippetTest.java
@@ -38,7 +38,7 @@
 /**
  * Test a scenario where the change of the package declaration causes a problem in a code snippet.
  */
-public void testChangePackage() {
+public void _testChangePackage() {
 	if (isJRockitVM()) return;
 	try {
 		// define the package
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java
index f888373..3e29c06 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java
@@ -65,7 +65,9 @@
 	if (osName.startsWith("Mac")) {
 		return new MacVMLauncher();
 	}
-	File file = new File(Util.getJREDirectory() + "/lib/rt.jar");
+	String javaVersion = System.getProperty("java.version");
+	boolean isJrt = javaVersion != null && javaVersion.length() > 0 && javaVersion.charAt(0) == '9';
+	File file = new File(Util.getJREDirectory() + (isJrt ?	"/jrt-fs.jar" :  "/lib/rt.jar"));
 	if (file.exists()) {
 		return new StandardVMLauncher();
 	}
@@ -128,14 +130,6 @@
 		// Use Runtime.exec(String[]) with tokens because Runtime.exec(String) with commandLineString
 		// does not properly handle spaces in arguments on Unix/Linux platforms.
 		String[] commandLine = getCommandLine();
-
-		// DEBUG
-		/*for (int i = 0; i < commandLine.length; i++) {
-			System.out.print(commandLine[i] + " ");
-		}
-		System.out.println();
-		*/
-
 		vmProcess= Runtime.getRuntime().exec(commandLine);
 	} catch (IOException e) {
 		throw new TargetException("Error launching VM at " + this.vmPath);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/StandardVMLauncher.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/StandardVMLauncher.java
index 3723e57..d7236d6 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/StandardVMLauncher.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/StandardVMLauncher.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -28,10 +32,15 @@
 @SuppressWarnings({ "rawtypes" ,"unchecked" })
 public class StandardVMLauncher extends LocalVMLauncher {
 	String batchFileName;
+	private boolean isJrtBasedVM;
 /**
  * Creates a new StandardVMLauncher that launches a standard VM
  * on the same machine.
  */
+public StandardVMLauncher(boolean isJrtBasedVM) {
+	super();
+	this.isJrtBasedVM = isJrtBasedVM;
+}
 public StandardVMLauncher() {
 	super();
 }
@@ -50,17 +59,19 @@
 			bootPathString.append(pathSeparator);
 		}
 	} else {
-		// Add regular rt.jar
-		bootPathString.append(this.vmPath);
-		bootPathString.append(File.separator);
-		if (!(this.vmPath.toLowerCase().endsWith("jre") || this.vmPath.toLowerCase().endsWith("jre" + File.separator))) {
-			bootPathString.append("jre");
+		if (!this.isJrtBasedVM) {
+			// Add regular rt.jar
+			bootPathString.append(this.vmPath);
 			bootPathString.append(File.separator);
+			if (!(this.vmPath.toLowerCase().endsWith("jre") || this.vmPath.toLowerCase().endsWith("jre" + File.separator))) {
+				bootPathString.append("jre");
+				bootPathString.append(File.separator);
+			}
+			bootPathString.append("lib");
+			bootPathString.append(File.separator);
+			bootPathString.append("rt.jar");
+			bootPathString.append(pathSeparator);
 		}
-		bootPathString.append("lib");
-		bootPathString.append(File.separator);
-		bootPathString.append("rt.jar");
-		bootPathString.append(pathSeparator);
 	}
 
 	// Add boot class path directory if needed
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index e8ef9c1..33def68 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -37,6 +41,7 @@
 	public static final int F_1_6 = 0x08;
 	public static final int F_1_7 = 0x10;
 	public static final int F_1_8 = 0x20;
+	public static final int F_9   = 0x40;
 
 	public static final boolean RUN_JAVAC = CompilerOptions.ENABLED.equals(System.getProperty("run.javac"));
 	private static final int UNINITIALIZED = -1;
@@ -45,6 +50,7 @@
 
 	protected long complianceLevel;
 	protected boolean enableAPT = false;
+	protected static boolean isJRE9 = false; // Stop gap, so tests need not be run at 9, but some tests can be adjusted for JRE 9
 
 	/**
 	 * Build a test suite made of test suites for all possible running VM compliances .
@@ -79,6 +85,9 @@
 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_8));
 		}
+		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
+			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK9));
+		}
 	}
 
 	/**
@@ -112,6 +121,9 @@
 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_8));
 		}
+		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
+			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK9));
+		}
 		return suite;
 	}
 
@@ -235,6 +247,14 @@
 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_8));
 			}
 		}
+		int level19 = complianceLevels & AbstractCompilerTest.F_9;
+		if (level19 != 0) {
+			if (level19 < minimalCompliance) {
+				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK9)+"!");
+			} else {
+				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK9));
+			}
+		}
 		return suite;
 	}
 
@@ -251,7 +271,9 @@
 		long highestLevel = highestComplianceLevels();
 		if (highestLevel < uniqueCompliance) {
 			String complianceString;
-			if (highestLevel == ClassFileConstants.JDK1_8)
+			if (highestLevel == ClassFileConstants.JDK9)
+				complianceString = "9";
+			else if (highestLevel == ClassFileConstants.JDK1_8)
 				complianceString = "1.8";
 			else if (highestLevel == ClassFileConstants.JDK1_7)
 				complianceString = "1.7";
@@ -281,6 +303,9 @@
 	 */
 	public static long highestComplianceLevels() {
 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
+		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
+			return ClassFileConstants.JDK9;
+		}
 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
 			return ClassFileConstants.JDK1_8;
 		}
@@ -304,6 +329,8 @@
 	 */
 	public static int getPossibleComplianceLevels() {
 		if (possibleComplianceLevels == UNINITIALIZED) {
+			String specVersion = System.getProperty("java.specification.version");
+			isJRE9 = CompilerOptions.VERSION_9.equals(specVersion);
 			String compliance = System.getProperty("compliance");
 			if (compliance != null) {
 				if (CompilerOptions.VERSION_1_3.equals(compliance)) {
@@ -318,6 +345,8 @@
 					possibleComplianceLevels = F_1_7;
 				} else if (CompilerOptions.VERSION_1_8.equals(compliance)) {
 					possibleComplianceLevels = F_1_8;
+				} else if (CompilerOptions.VERSION_9.equals(compliance)) {
+					possibleComplianceLevels = F_9;
 				} else {
 					System.out.println("Invalid compliance specified (" + compliance + ")");
 					System.out.print("Use one of ");
@@ -326,12 +355,12 @@
 					System.out.print(CompilerOptions.VERSION_1_5 + ", ");
 					System.out.print(CompilerOptions.VERSION_1_6 + ", ");
 					System.out.print(CompilerOptions.VERSION_1_7 + ", ");
-					System.out.println(CompilerOptions.VERSION_1_8);
+					System.out.print(CompilerOptions.VERSION_1_8 + ", ");
+					System.out.println(CompilerOptions.VERSION_9);
 					System.out.println("Defaulting to all possible compliances");
 				}
 			}
 			if (possibleComplianceLevels == UNINITIALIZED) {
-				String specVersion = System.getProperty("java.specification.version");
 				if (!RUN_JAVAC) {
 					possibleComplianceLevels = F_1_3;
 					boolean canRun1_4 = !"1.0".equals(specVersion)
@@ -357,6 +386,10 @@
 					if (canRun1_8) {
 						possibleComplianceLevels |= F_1_8;
 					}
+					boolean canRun9 = canRun1_8 && !CompilerOptions.VERSION_1_8.equals(specVersion);
+					if (canRun9) {
+						possibleComplianceLevels |= F_9;
+					}
 				} else if ("1.0".equals(specVersion)
 							|| CompilerOptions.VERSION_1_1.equals(specVersion)
 							|| CompilerOptions.VERSION_1_2.equals(specVersion)
@@ -371,6 +404,9 @@
 							possibleComplianceLevels |= F_1_7;
 							if (!CompilerOptions.VERSION_1_7.equals(specVersion)) {
 								possibleComplianceLevels |= F_1_8;
+								if (!CompilerOptions.VERSION_1_8.equals(specVersion)) {
+									possibleComplianceLevels |= F_9;
+								}
 							}
 						}
 					}
@@ -473,6 +509,16 @@
 		return (AbstractCompilerTest.getPossibleComplianceLevels() & compliance) != 0;
 	}
 
+	public String decorateAnnotationValueLiteral(String val) {
+		if (!isJRE9) {
+			return val;
+		}
+		StringBuilder builder = new StringBuilder(val);
+		builder.insert(0, "\"");
+		builder.append("\"");
+		return builder.toString();
+	}
+
 	public AbstractCompilerTest(String name) {
 		super(name);
 	}
@@ -504,6 +550,10 @@
 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
+		} else if (this.complianceLevel == ClassFileConstants.JDK9) {
+			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
+			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
+			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
 		}
 		return options;
 	}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
index c2bcadf..d9ab9b3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -33,6 +33,7 @@
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
@@ -724,6 +725,18 @@
  * Returns null if none could be found.
 */
 public static String[] getJavaClassLibs() {
+	String javaVersion = System.getProperty("java.version");
+	if (javaVersion.length() > 3) {
+		javaVersion = javaVersion.substring(0, 3);
+	}
+	long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion);
+	if (jdkLevel >= ClassFileConstants.JDK9) {
+		String jreDir = getJREDirectory();
+		return new String[] {
+				toNativePath(jreDir + "/lib/jrt-fs.jar")
+		};
+	}
+
 	// check bootclasspath properties for Sun, JRockit and Harmony VMs
 	String bootclasspathProperty = System.getProperty("sun.boot.class.path"); //$NON-NLS-1$
 	if ((bootclasspathProperty == null) || (bootclasspathProperty.length() == 0)) {
diff --git a/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8.jar b/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8.jar
index c188b24..1a9814e 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8.jar
+++ b/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8src.zip b/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8src.zip
index 4a9f8e7..ce569be 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8src.zip
+++ b/org.eclipse.jdt.core.tests.model/JCL/converterJclMin1.8src.zip
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin9.jar b/org.eclipse.jdt.core.tests.model/JCL/jclMin9.jar
new file mode 100644
index 0000000..6f2af93
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin9.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin9src.zip b/org.eclipse.jdt.core.tests.model/JCL/jclMin9src.zip
new file mode 100644
index 0000000..d46027f
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin9src.zip
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java
new file mode 100644
index 0000000..68cfd89
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.jdt.core.tests.dom.ASTConverter9Test;
+import org.eclipse.jdt.core.tests.dom.ConverterTestSetup;
+import org.eclipse.jdt.core.tests.model.CompletionTests9;
+import org.eclipse.jdt.core.tests.model.Java9ElementTests;
+import org.eclipse.jdt.core.tests.model.JavaSearchBugs9Tests;
+import org.eclipse.jdt.core.tests.model.ModuleBuilderTests;
+import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class RunAllJava9Tests extends TestCase {
+
+	public RunAllJava9Tests(String name) {
+		super(name);
+	}
+	public static Class[] getAllTestClasses() {
+		return new Class[] {
+			ModuleBuilderTests.class,
+			Java9ElementTests.class,
+			JavaSearchBugs9Tests.class,
+			CompletionTests9.class,
+		};
+	}
+
+	public static Class[] getConverterTestClasses() {
+		return new Class[] {
+				ASTConverter9Test.class,
+		};
+	}
+
+	public static Class[] getCompilerClasses() {
+		return new Class[] {
+			org.eclipse.jdt.core.tests.eval.TestAll.class,
+			org.eclipse.jdt.core.tests.compiler.regression.TestAll.class,
+		};
+	}
+
+	public static Test suite() {
+		TestSuite ts = new TestSuite(RunAllJava9Tests.class.getName());
+
+		Class[] testClasses = getAllTestClasses();
+		addTestsToSuite(ts, testClasses);
+		testClasses = getConverterTestClasses();
+		addTestsToSuite(ts, testClasses);
+
+		AbstractCompilerTest.setpossibleComplianceLevels(AbstractCompilerTest.F_9);
+		addTestsToSuite(ts, getCompilerClasses());
+		// ComplianceDiagnoseTest is already added to the test suite through getTestSuite
+		ts.addTest(org.eclipse.jdt.core.tests.compiler.parser.TestAll.getTestSuite(false));
+		return ts;
+	}
+	public static void addTestsToSuite(TestSuite suite, Class[] testClasses) {
+
+		for (int i = 0; i < testClasses.length; i++) {
+			Class testClass = testClasses[i];
+			// call the suite() method and add the resulting suite to the suite
+			try {
+				Method suiteMethod = testClass.getDeclaredMethod("suite", new Class[0]); //$NON-NLS-1$
+				Test test = (Test)suiteMethod.invoke(null, new Object[0]);
+				suite.addTest(test);
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+			} catch (InvocationTargetException e) {
+				e.getTargetException().printStackTrace();
+			} catch (NoSuchMethodException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+	protected void tearDown() throws Exception {
+		ConverterTestSetup.PROJECT_SETUP = false;
+		super.tearDown();
+	}
+}
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 171aac2..ad8744c 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, 2014 IBM Corporation and others.
+ * Copyright (c) 2011, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -41,7 +41,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(getJLS8());
 	}
 
 	public ASTConverter15JLS8Test(String name) {
@@ -392,7 +392,7 @@
 	public void test0006() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0006", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		final String expectedOutput = "Package annotations must be in file package-info.java";
@@ -412,7 +412,7 @@
 	public void test0007() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0007", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertProblemsSize(compilationUnit, 0);
@@ -441,7 +441,7 @@
 
 	public void test0009() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0009", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -465,7 +465,7 @@
 
 	public void test0010() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0010", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -495,7 +495,7 @@
 
 	public void test0011() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0011", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -526,7 +526,7 @@
 
 	public void test0012() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0012", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -2230,7 +2230,7 @@
 	 */
 	public void test0072() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15", "src", "test0072", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 0);
@@ -3254,7 +3254,7 @@
 			"}";
 		this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents.toCharArray());
-		ASTNode node = runConversion(AST.JLS8, this.workingCopy, true);		
+		ASTNode node = runConversion(getJLS8(), this.workingCopy, true);		
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit compilationUnit = (CompilationUnit) node;
 		String expectedOutput = "Dead code";
@@ -4304,6 +4304,7 @@
 
 	/**
 	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=84358
+	 * @deprecated references deprecated code
 	 */
 	public void test0139() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0139", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -5912,7 +5913,7 @@
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=99510
 	public void test0191() throws CoreException, IOException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0191", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No node", node);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
@@ -7522,7 +7523,7 @@
 		IType type = sourceUnit.getType("Test3");//$NON-NLS-1$
 
 		assertNotNull("Should not be null", type);
-		ASTParser parser= ASTParser.newParser(AST.JLS8);
+		ASTParser parser= ASTParser.newParser(getJLS8());
 		parser.setProject(type.getJavaProject());
 		IBinding[] bindings= parser.createBindings(new IJavaElement[] { type }, null);
 		if (bindings.length == 1 && bindings[0] instanceof ITypeBinding) {
@@ -7550,7 +7551,7 @@
 		IType type = sourceUnit.getType("Test3");//$NON-NLS-1$
 
 		assertNotNull("Should not be null", type);
-		ASTParser parser= ASTParser.newParser(AST.JLS8);
+		ASTParser parser= ASTParser.newParser(getJLS8());
 		parser.setSource(sourceUnit);
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setResolveBindings(true);
@@ -8132,7 +8133,7 @@
 	 */
 	public void test0247() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0247", "EclipseCompiler.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 		assertNotNull("Not a compilation unit", result);
 	}
 
@@ -8271,7 +8272,7 @@
 	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=174436
 	public void test0251() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0251", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -8301,7 +8302,7 @@
 	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=174436
 	public void test0252() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter15" , "src", "test0252", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -8341,7 +8342,7 @@
 			"}";
 		this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents);
-		ASTNode node = runConversion(AST.JLS8, this.workingCopy, true, true, true);
+		ASTNode node = runConversion(getJLS8(), this.workingCopy, true, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		String expectedError = "List cannot be resolved to a type";
@@ -8379,7 +8380,7 @@
 			"}";
 		this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents);
-		ASTNode node = runConversion(AST.JLS8, this.workingCopy, true, true, true);
+		ASTNode node = runConversion(getJLS8(), this.workingCopy, true, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -9451,7 +9452,7 @@
 		}
 
 		CompilationUnitRequestor requestor = new CompilationUnitRequestor();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setResolveBindings(true);
 		parser.setProject(getJavaProject("Converter15"));
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
@@ -9627,7 +9628,7 @@
 			"}";
 		this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents);
-		ASTNode node = runConversion(AST.JLS8, this.workingCopy, true, true, true);
+		ASTNode node = runConversion(getJLS8(), this.workingCopy, true, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -9681,7 +9682,7 @@
 			"}";
 		this.workingCopy = getWorkingCopy("/Converter15/src/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents);
-		ASTNode node = runConversion(AST.JLS8, this.workingCopy, true, true, true);
+		ASTNode node = runConversion(getJLS8(), this.workingCopy, true, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 1, "Bar2 cannot be resolved to a type");
@@ -10756,7 +10757,7 @@
 			BindingKey.createTypeBindingKey(typeName)
 		};
 		final BindingRequestor requestor = new BindingRequestor();
-		final ASTParser parser = ASTParser.newParser(AST.JLS8);
+		final ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setResolveBindings(true);
 		parser.setProject(javaProject);
 		// this doesn't really do a parse; it's a type lookup
@@ -10791,7 +10792,7 @@
 			BindingKey.createTypeBindingKey(typeName)
 		};
 		final BindingRequestor requestor = new BindingRequestor();
-		final ASTParser parser = ASTParser.newParser(AST.JLS8);
+		final ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setResolveBindings(true);
 		parser.setProject(javaProject);
 		// this doesn't really do a parse; it's a type lookup
@@ -10829,7 +10830,7 @@
 			BindingKey.createTypeBindingKey(typeName)
 		};
 		final BindingRequestor requestor = new BindingRequestor();
-		final ASTParser parser = ASTParser.newParser(AST.JLS8);
+		final ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setResolveBindings(true);
 		parser.setProject(javaProject);
 		// this doesn't really do a parse; it's a type lookup
@@ -11252,7 +11253,7 @@
 		//IType type2 = sourceUnit2.getType("TestAnnotationWithStringDefault");//$NON-NLS-1$
 
 		assertNotNull("Should not be null", type);
-		ASTParser parser= ASTParser.newParser(AST.JLS8);
+		ASTParser parser= ASTParser.newParser(getJLS8());
 		parser.setProject(type.getJavaProject());
 		IBinding[] bindings= parser.createBindings(new IJavaElement[] { type }, null);
 		if (bindings.length == 1 && bindings[0] instanceof ITypeBinding) {
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 a729768..6e0d142 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -37,7 +41,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(getAST8());
 	}
 
 	public ASTConverter18Test(String name) {
@@ -52,7 +56,12 @@
 	public static Test suite() {
 		return buildModelTestSuite(ASTConverter18Test.class);
 	}
-
+	/**
+	 * @deprecated
+	 */
+	static int getAST8() {
+		return AST.JLS8;
+	}
 	protected void tearDown() throws Exception {
 		super.tearDown();
 		if (this.workingCopy != null) {
@@ -3922,7 +3931,7 @@
 				"}\n";
 		this.workingCopy = getWorkingCopy("/Converter18/src/test/X.java", true/*resolve*/);
 		this.workingCopy.getBuffer().setContents(contents);
-		CompilationUnit compilationUnit = this.workingCopy.reconcile(AST.JLS8, ICompilationUnit.FORCE_PROBLEM_DETECTION, null, null);
+		CompilationUnit compilationUnit = this.workingCopy.reconcile(getAST8(), ICompilationUnit.FORCE_PROBLEM_DETECTION, null, null);
 		ASTNode node = getASTNode(compilationUnit, 0);
 		FieldDeclaration[] field = ((TypeDeclaration) node).getFields();
 		List fragments = field[0].fragments();
@@ -4361,7 +4370,7 @@
 		}
 	}
 	final BindingRequestor requestor = new BindingRequestor();
-	final ASTParser parser = ASTParser.newParser(AST.JLS8);
+	final ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setResolveBindings(false);
 	parser.setProject(javaProject);
 	try {
@@ -4390,7 +4399,7 @@
 			"@interface TU { }";
 	this.workingCopy = getWorkingCopy("/Converter18/src/com/test/todo/Test.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4434,7 +4443,7 @@
 	};
 	addLibrary(javaProject, jarName, srcName, contents, JavaCore.VERSION_1_8);
 
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setIgnoreMethodBodies(true);
 	parser.setProject(javaProject);
 	IType type = javaProject.findType("test406805.TestEnum");
@@ -4497,7 +4506,7 @@
 	};
 	addLibrary(javaProject, jarName, srcName, contents, JavaCore.VERSION_1_8, null);
 
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setIgnoreMethodBodies(true);
 	parser.setProject(javaProject);
 	IType type = javaProject.findType("test406805a.NestedTestEnum");
@@ -4558,7 +4567,7 @@
 	};
 	addLibrary(javaProject, jarName, srcName, contents, JavaCore.VERSION_1_8);
 
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setIgnoreMethodBodies(true);
 	parser.setProject(javaProject);
 	IType type = javaProject.findType("test406805b.TestEnum");
@@ -4620,7 +4629,7 @@
 	};
 	addLibrary(javaProject, jarName, srcName, contents, JavaCore.VERSION_1_8, null);
 
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setIgnoreMethodBodies(true);
 	parser.setProject(javaProject);
 	IType type = javaProject.findType("test406805d.NestedTestEnum");
@@ -4686,7 +4695,7 @@
 	};
 	addLibrary(javaProject, jarName, srcName, contents, JavaCore.VERSION_1_8);
 
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setIgnoreMethodBodies(true);
 	parser.setProject(javaProject);
 	IType type = javaProject.findType("test436347.TestEnum");
@@ -4726,7 +4735,7 @@
 			"}\n";
 	this.workingCopy = getWorkingCopy("/Converter18/src/Bug433879/X.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4748,7 +4757,7 @@
 			"}\n";
 	this.workingCopy = getWorkingCopy("/Converter18/src/Bug433879a/X.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4769,7 +4778,7 @@
 			"}\n";
 	this.workingCopy = getWorkingCopy("/Converter18/src/Bug433879c/X.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4796,7 +4805,7 @@
 			"}\n";
 	this.workingCopy = getWorkingCopy("/Converter18/src/Bug433879d/X.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4825,7 +4834,7 @@
 			"}\n";
 	this.workingCopy = getWorkingCopy("/Converter18/src/Bug433879e/X.java", true/*computeProblems*/);
 	try {
-		buildAST(AST.JLS8, contents, this.workingCopy, false, true, true);
+		buildAST(getAST8(), contents, this.workingCopy, false, true, true);
 	} catch (ClassCastException e) {
 		fail(e.getMessage());
 	}
@@ -4929,7 +4938,7 @@
 		}
 	}
 	final BindingRequestor requestor = new BindingRequestor();
-	final ASTParser parser = ASTParser.newParser(AST.JLS8);
+	final ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setResolveBindings(false);
 	parser.setProject(javaProject);
 	parser.setIgnoreMethodBodies(true);
@@ -5099,7 +5108,7 @@
 	this.workingCopy = getWorkingCopy("/Converter18/src/test460186/NPE.java", contents, false/*computeProblems*/);
 	IJavaProject javaProject = this.workingCopy.getJavaProject();
 
-	final ASTParser parser = ASTParser.newParser(AST.JLS8);
+	final ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setResolveBindings(false);
 	parser.setProject(javaProject);
 	parser.setIgnoreMethodBodies(false);
@@ -5124,7 +5133,7 @@
 	this.workingCopy = getWorkingCopy("/Converter18/src/test443232/E21.java", contents, false/*computeProblems*/);
 	IJavaProject javaProject = this.workingCopy.getJavaProject();
 
-	final ASTParser parser = ASTParser.newParser(AST.JLS8);
+	final ASTParser parser = ASTParser.newParser(getAST8());
 	parser.setResolveBindings(false);
 	parser.setProject(javaProject);
 	parser.setIgnoreMethodBodies(false);
@@ -5258,6 +5267,7 @@
 		}
 	}
 }
+@SuppressWarnings("deprecation")
 public void testBug500503() throws JavaModelException {
 	String contents =
 			"package test432051;\n" +
@@ -5292,4 +5302,43 @@
 	parser.createASTs(new ICompilationUnit[] {this.workingCopy}, new String[0], requestor, null);
 }
 
+public void testBug497719_0001() throws JavaModelException {
+	String contents =
+			"import java.io.IOException;\n" +
+			"\n" +
+			"class Z {\n" +
+			"	 final Y yz = new Y();\n" +
+			"}\n" +
+			"public class X extends Z {\n" +
+			"	final  Y y2 = new Y();\n" +
+			"	\n" +
+			"	 Y bar() {\n" +
+			"		 return new Y();\n" +
+			"	 }\n" +
+			"	public void foo() {\n" +
+			"		Y y3 = new Y();\n" +
+			"		int a[];\n" +
+			"		try (y3; y3;super.yz;super.yz;this.y2;Y y4 = new Y())  {  \n" +
+			"			System.out.println(\"In Try\");\n" +
+			"		} catch (IOException e) {			  \n" +
+			"		} \n" +
+			"	}\n" +
+			"	public static void main(String[] args) {\n" +
+			"		new X().foo();\n" +
+			"	}\n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	@Override\n" +
+			"	public void close() throws IOException {\n" +
+			"		System.out.println(\"Closed\");\n" +
+			"	}  \n" +
+			"}";
+		this.workingCopy = getWorkingCopy("/Converter8/src/X.java", true/*resolve*/);
+		ASTNode node = buildAST(contents, this.workingCopy, false);
+		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+		node = getASTNode((CompilationUnit)node, 1, 2);
+		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+		TryStatement tryStatement = (TryStatement)methodDeclaration.getBody().statements().get(2);
+		assertEquals("Try Statement should be malformed", ASTNode.MALFORMED, (tryStatement.getFlags() & ASTNode.MALFORMED));
+}
 }
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
new file mode 100644
index 0000000..b7af7ac
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.dom;
+
+import junit.framework.Test;
+
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.JrtPackageFragmentRoot;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+@SuppressWarnings({"rawtypes"})
+public class ASTConverter9Test extends ConverterTestSetup {
+
+	ICompilationUnit workingCopy;
+	private static boolean isJRE9 = false;
+
+	public void setUpSuite() throws Exception {
+		super.setUpSuite();
+		this.ast = AST.newAST(AST_INTERNAL_JLS9);
+	}
+
+	public ASTConverter9Test(String name) {
+		super(name);
+	}
+
+	static {
+//		TESTS_NUMBERS = new int[] { 19 };
+//		TESTS_RANGE = new int[] { 1, -1 };
+//		TESTS_NAMES = new String[] {"testBug512023_0001"};
+	}
+	public static Test suite() {
+		String javaVersion = System.getProperty("java.version");
+		if (javaVersion.length() > 3) {
+			javaVersion = javaVersion.substring(0, 3);
+		}
+		long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion);
+		if (jdkLevel >= ClassFileConstants.JDK9) {
+			isJRE9 = true;
+		}
+		return buildModelTestSuite(ASTConverter9Test.class);
+	}
+
+	protected void tearDown() throws Exception {
+		super.tearDown();
+		if (this.workingCopy != null) {
+			this.workingCopy.discardWorkingCopy();
+			this.workingCopy = null;
+		}
+	}
+
+	public void testBug497719_0001() throws JavaModelException {
+		ICompilationUnit sourceUnit = getCompilationUnit("Converter9" , "src", "testBug497719_001", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		ASTNode result = runConversion(this.ast.apiLevel(), sourceUnit, true, true);
+		char[] source = sourceUnit.getSource().toCharArray();
+		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
+		CompilationUnit compilationUnit = (CompilationUnit) result;
+		assertProblemsSize(compilationUnit, 0);
+		ASTNode node = getASTNode(compilationUnit, 0, 0);
+		assertEquals("Not a compilation unit", ASTNode.METHOD_DECLARATION, node.getNodeType());
+		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+		TryStatement tryStatement = (TryStatement) methodDeclaration.getBody().statements().get(1);
+		List list = tryStatement.resources();
+		VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) list.get(0);
+		checkSourceRange(variableDeclarationExpression, "final Y y = new Y()", source);
+		SimpleName simpleName = (SimpleName) list.get(1);
+		checkSourceRange(simpleName, "y1", source);
+		variableDeclarationExpression = (VariableDeclarationExpression) list.get(2);
+		checkSourceRange(variableDeclarationExpression, "final Y y2 = new Y()", source);
+		
+	}
+	
+	public void testBug497719_0002() throws JavaModelException {
+		String contents =
+				"import java.io.IOException;\n" +
+				"\n" +
+				"class Z {\n" +
+				"	 final Y yz = new Y();\n" +
+				"}\n" +
+				"public class X extends Z {\n" +
+				"	final  Y y2 = new Y();\n" +
+				"	\n" +
+				"	 Y bar() {\n" +
+				"		 return new Y();\n" +
+				"	 }\n" +
+				"	public void foo() {\n" +
+				"		Y y3 = new Y();\n" +
+				"		int a[];\n" +
+				"		try (y3; y3;super.yz;super.yz;this.y2;Y y4 = new Y())  {  \n" +
+				"			System.out.println(\"In Try\");\n" +
+				"		} catch (IOException e) {			  \n" +
+				"		} \n" +
+				"	}\n" +
+				"	public static void main(String[] args) {\n" +
+				"		new X().foo();\n" +
+				"	}\n" +
+				"}\n" +
+				"class Y implements AutoCloseable {\n" +
+				"	@Override\n" +
+				"	public void close() throws IOException {\n" +
+				"		System.out.println(\"Closed\");\n" +
+				"	}  \n" +
+				"}";
+			this.workingCopy = getWorkingCopy("/Converter9/src/X.java", true/*resolve*/);
+			ASTNode node = buildAST(contents, this.workingCopy, false);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+			node = getASTNode((CompilationUnit)node, 1, 2);
+			MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+			TryStatement tryStatement = (TryStatement)methodDeclaration.getBody().statements().get(2);
+			List<Expression> resources = tryStatement.resources();
+			Expression expr = resources.get(0);
+			SimpleName simpleName = (SimpleName) expr;
+			checkSourceRange(simpleName, "y3", contents);
+			expr = resources.get(1);
+			simpleName = (SimpleName) expr;
+			checkSourceRange(expr, "y3", contents);
+			expr = resources.get(2);
+			SuperFieldAccess superFieldAccess = (SuperFieldAccess) expr;
+			checkSourceRange(superFieldAccess, "super.yz", contents);
+			expr = resources.get(3);
+			superFieldAccess = (SuperFieldAccess) expr;
+			checkSourceRange(superFieldAccess, "super.yz", contents);
+			expr = resources.get(4);
+			FieldAccess fieldAccess = (FieldAccess) expr;
+			checkSourceRange(fieldAccess, "this.y2", contents);
+			expr = resources.get(5);
+			VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expr;
+			checkSourceRange(variableDeclarationExpression, "Y y4 = new Y()", contents);
+	}
+	public void testBug496123_0001() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		String content =  "module first {"
+				+ "  requires second;\n"
+				+ "  exports pack11 to third, fourth;\n"
+				+ "  uses NewType;\n"
+				+ "  provides pack22.I22 with pack11.packinternal.Z11;\n"
+				+ "}";
+		this.workingCopies[0] = getWorkingCopy(
+				"/Converter9/src/module-info.java", content);
+		
+		CompilationUnit unit = (CompilationUnit) runConversion(AST_INTERNAL_JLS9, this.workingCopies[0], false/*no bindings*/);
+		ModuleDeclaration moduleDecl = unit.getModule();
+		
+		checkSourceRange(moduleDecl, content, content);
+		List<ModuleStatement> stmts = moduleDecl.moduleStatements();
+		assertTrue(stmts.size() > 0);
+		
+		RequiresStatement req = (RequiresStatement) stmts.get(0);
+		checkSourceRange(req, "requires second;", content);
+		
+		ExportsStatement exp = (ExportsStatement) stmts.get(1);
+		checkSourceRange(exp, "exports pack11 to third, fourth;", content);
+		checkSourceRange(exp.getName(), "pack11", content);
+		List<Name> modules = exp.modules();
+		assertTrue(modules.size() == 2);
+		checkSourceRange(modules.get(0), "third", content);
+		checkSourceRange(modules.get(1), "fourth", content);
+		
+		UsesStatement u = (UsesStatement) stmts.get(2);
+		checkSourceRange(u, "uses NewType;", content);
+		Type type = u.getType();
+		checkSourceRange(type, "NewType", content);
+		
+		ProvidesStatement p = (ProvidesStatement) stmts.get(3);
+		checkSourceRange(p, "provides pack22.I22 with pack11.packinternal.Z11;", content);
+		type = p.getType();
+		checkSourceRange(type, "pack22.I22", content);
+		List<Type> impls = p.implementations();
+		assertTrue(impls.size() > 0);
+		type = impls.get(0);
+		checkSourceRange(type, "pack11.packinternal.Z11", content);		
+	}
+
+	public void testBug512023_0001() throws Exception {
+		try {
+			IJavaProject project1 = createJavaProject("ConverterTests9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String content = 
+				"module first {\n" +
+				"    requires second.third;\n" +
+				"    exports pack1.X11 to org.eclipse.jdt;\n" +
+				"}";
+			createFile("/ConverterTests9/src/module-info.java",	content);
+			createFolder("/ConverterTests9/src/pack1");
+			createFile("/ConverterTests9/src/pack1/X11.java",
+					"package pack1;\n" +
+					"public class X11 {}\n");
+			this.workingCopy = getWorkingCopy("/ConverterTests9/src/module-info.java", false);
+			ASTNode node = buildAST(content, this.workingCopy, false);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+			CompilationUnit unit = (CompilationUnit) node;
+			ModuleDeclaration moduleDecl = unit.getModule();
+
+			checkSourceRange(moduleDecl, content, content);
+			List<ModuleStatement> stmts = moduleDecl.moduleStatements();
+			assertTrue(stmts.size() > 0);
+
+			QualifiedName qName;
+			RequiresStatement req = (RequiresStatement) stmts.get(0);
+			qName = (QualifiedName) req.getName();
+			checkSourceRange(qName, "second.third", content);
+			checkSourceRange(qName.getName(), "third", content);
+			checkSourceRange(qName.getQualifier(), "second", content);
+
+			ExportsStatement exp = (ExportsStatement) stmts.get(1);
+			checkSourceRange(exp, "exports pack1.X11 to org.eclipse.jdt;", content);
+			qName = (QualifiedName) exp.getName();
+			checkSourceRange(qName, "pack1.X11", content);
+			checkSourceRange(qName.getName(), "X11", content);
+			checkSourceRange(qName.getQualifier(), "pack1", content);
+
+			List<Name> modules = exp.modules();
+			qName = (QualifiedName) modules.get(0);
+			checkSourceRange(qName, "org.eclipse.jdt", content);
+			checkSourceRange(qName.getName(), "jdt", content);
+			checkSourceRange(qName.getQualifier(), "org.eclipse", content);
+		} finally {
+			deleteProject("ConverterTests9");
+		}
+	}
+	public void testBug514417() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			createJava9Project("Bug514417", new String[]{"src"});
+			createFolder("/Bug514417/src/pack1");
+			String content =  "package pack1;\n" +
+					"import java.lang.String;\n" +
+					"public class X { \n" +
+					"	java.lang.String str = null;\n" +
+					"}\n";
+			createFile("/Bug514417/src/pack1/X.java", content);
+			ICompilationUnit sourceUnit = getCompilationUnit("Bug514417" , "src", "pack1", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+			ASTNode unit = runConversion(AST_INTERNAL_JLS9, sourceUnit, true);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, unit.getNodeType());
+			List imps = ((CompilationUnit) unit).imports();
+			assertEquals("import missing", 1, imps.size());
+			ImportDeclaration impo = (ImportDeclaration) imps.get(0);
+			IBinding bind = impo.resolveBinding();
+			assertNotNull("binding null", bind);
+			IJavaElement element = bind.getJavaElement();
+			assertNotNull(element);
+			assertEquals("Incorrect element type", IJavaElement.TYPE, element.getElementType());
+			IType type = (IType) element;
+			assertEquals("Incorrect name", "java.lang.String", type.getFullyQualifiedName());
+			element = element.getParent();
+			assertNotNull(element);
+			assertEquals("Incorrect element type", IJavaElement.CLASS_FILE, element.getElementType());
+			element = element.getParent();
+			assertNotNull(element);
+			assertEquals("Incorrect element type", IJavaElement.PACKAGE_FRAGMENT, element.getElementType());
+			element = element.getParent();
+			assertNotNull(element);
+			assertEquals("Incorrect element type", IJavaElement.PACKAGE_FRAGMENT_ROOT, element.getElementType());
+			assertTrue("incorrect root type", (element instanceof JrtPackageFragmentRoot));
+			JrtPackageFragmentRoot root = (JrtPackageFragmentRoot) element;
+			assertEquals("incorrect module name", "java.base", root.getElementName());
+		} finally {
+			deleteProject("Bug514417");
+		}
+	}
+// Add new tests here 
+}
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 9952e12..c4cea87 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, 2015 IBM Corporation and others.
+ * Copyright (c) 2011, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,7 +25,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(getJLS8());
 	}
 
 	public ASTConverterAST8Test(String name) {
@@ -50,7 +50,7 @@
 	public void test0001() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0001", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 
 		// check that we have the right tree
 		CompilationUnit unit = this.ast.newCompilationUnit();
@@ -119,7 +119,7 @@
 	public void test0002() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0002", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
@@ -134,7 +134,7 @@
 	public void test0003() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0003", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
@@ -155,7 +155,7 @@
 	public void test0004() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0004", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
@@ -179,7 +179,7 @@
 	public void test0005() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0005", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
@@ -206,7 +206,7 @@
 	public void test0006() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0006", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
@@ -236,7 +236,7 @@
 	public void test0007() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0007", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("Not an ExpressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node;
@@ -257,7 +257,7 @@
 	public void test0008() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0008", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
@@ -278,7 +278,7 @@
 	public void test0009() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0009", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
@@ -301,7 +301,7 @@
 	public void test0010() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0010", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
@@ -317,7 +317,7 @@
 	public void test0011() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0011", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
@@ -333,7 +333,7 @@
 	public void test0012() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0012", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
@@ -354,7 +354,7 @@
 	public void test0013() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0013", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -371,7 +371,7 @@
 	public void test0014() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0014", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -390,7 +390,7 @@
 	public void test0015() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0015", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -408,7 +408,7 @@
 	public void test0016() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0016", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -426,7 +426,7 @@
 	public void test0017() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0017", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -444,7 +444,7 @@
 	public void test0018() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0018", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -462,7 +462,7 @@
 	public void test0019() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0019", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -480,7 +480,7 @@
 	public void test0020() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0020", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -498,7 +498,7 @@
 	public void test0021() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0021", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -516,7 +516,7 @@
 	public void test0022() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0022", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -534,7 +534,7 @@
 	public void test0023() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0023", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -552,7 +552,7 @@
 	public void test0024() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0024", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -570,7 +570,7 @@
 	public void test0025() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0025", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -588,7 +588,7 @@
 	public void test0026() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0026", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Assignment assignment = this.ast.newAssignment();
@@ -606,7 +606,7 @@
 	public void test0027() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0027", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
@@ -623,7 +623,7 @@
 	public void test0028() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0028", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
@@ -640,7 +640,7 @@
 	public void test0029() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0029", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		PostfixExpression postfixExpression = this.ast.newPostfixExpression();
@@ -657,7 +657,7 @@
 	public void test0030() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0030", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		PostfixExpression postfixExpression = this.ast.newPostfixExpression();
@@ -674,7 +674,7 @@
 	public void test0031() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0031", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -695,7 +695,7 @@
 	public void test0032() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0032", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -716,7 +716,7 @@
 	public void test0033() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0033", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -739,7 +739,7 @@
 	public void test0034() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0034", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -762,7 +762,7 @@
 	public void test0035() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0035", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -785,7 +785,7 @@
 	public void test0036() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0036", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -808,7 +808,7 @@
 	public void test0037() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0037", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -831,7 +831,7 @@
 	public void test0038() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0038", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -853,7 +853,7 @@
 	public void test0039() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0039", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -875,7 +875,7 @@
 	public void test0040() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0040", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -897,7 +897,7 @@
 	public void test0041() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0041", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -919,7 +919,7 @@
 	public void test0042() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0042", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		BooleanLiteral literal = this.ast.newBooleanLiteral(false);
@@ -933,7 +933,7 @@
 	public void test0043() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0043", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		BooleanLiteral literal = this.ast.newBooleanLiteral(true);
@@ -947,7 +947,7 @@
 	public void test0044() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0044", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NullLiteral literal = this.ast.newNullLiteral();
@@ -961,7 +961,7 @@
 	public void test0045() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0045", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		CharacterLiteral literal = this.ast.newCharacterLiteral();
@@ -976,7 +976,7 @@
 	public void test0046() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0046", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("1.00001");//$NON-NLS-1$
@@ -990,7 +990,7 @@
 	public void test0047() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0047", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("1.00001f");//$NON-NLS-1$
@@ -1004,7 +1004,7 @@
 	public void test0048() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0048", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("30000");//$NON-NLS-1$
@@ -1018,7 +1018,7 @@
 	public void test0049() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0049", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("-2147483648");//$NON-NLS-1$
@@ -1032,7 +1032,7 @@
 	public void test0050() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0050", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("2147483648L");//$NON-NLS-1$
@@ -1046,7 +1046,7 @@
 	public void test0051() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0051", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("2147483648L");//$NON-NLS-1$
@@ -1063,7 +1063,7 @@
 	public void test0052() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0052", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		NumberLiteral literal = this.ast.newNumberLiteral("-9223372036854775808L");//$NON-NLS-1$
@@ -1077,7 +1077,7 @@
 	public void test0053() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0053", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		/*
@@ -1102,7 +1102,7 @@
 	public void test0054() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0054", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1126,7 +1126,7 @@
 	public void test0055() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0055", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1150,7 +1150,7 @@
 	public void test0056() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0056", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1174,7 +1174,7 @@
 	public void test0057() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0057", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1198,7 +1198,7 @@
 	public void test0058() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0058", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1222,7 +1222,7 @@
 	public void test0059() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0059", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1246,7 +1246,7 @@
 	public void test0060() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0060", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1270,7 +1270,7 @@
 	public void test0061() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0061", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1294,7 +1294,7 @@
 	public void test0062() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0062", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1318,7 +1318,7 @@
 	public void test0063() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0063", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1342,7 +1342,7 @@
 	public void test0064() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0064", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1366,7 +1366,7 @@
 	public void test0065() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0065", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1390,7 +1390,7 @@
 	public void test0066() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0066", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1414,7 +1414,7 @@
 	public void test0067() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0067", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1438,7 +1438,7 @@
 	public void test0068() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0068", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1462,7 +1462,7 @@
 	public void test0069() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0069", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1486,7 +1486,7 @@
 	public void test0070() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0070", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -1509,7 +1509,7 @@
 	public void test0071() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0071", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1539,7 +1539,7 @@
 	public void test0072() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0072", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -1561,7 +1561,7 @@
 	public void test0073() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0073", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -1583,7 +1583,7 @@
 	public void test0074() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0074", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1606,7 +1606,7 @@
 	public void test0075() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0075", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1630,7 +1630,7 @@
 	public void test0076() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0076", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1657,7 +1657,7 @@
 	public void test0077() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0077", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
@@ -1684,7 +1684,7 @@
 	public void test0078() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0078", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		SuperMethodInvocation superMethodInvocation = this.ast.newSuperMethodInvocation();
@@ -1700,7 +1700,7 @@
 	public void test0079() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0079", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		SuperMethodInvocation superMethodInvocation = this.ast.newSuperMethodInvocation();
@@ -1717,7 +1717,7 @@
 	public void test0080() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0080", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		MethodInvocation methodInvocation = this.ast.newMethodInvocation();
@@ -1734,7 +1734,7 @@
 	public void test0081() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0081", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		MethodInvocation methodInvocation = this.ast.newMethodInvocation();
@@ -1752,7 +1752,7 @@
 	public void test0082() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0082", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1767,7 +1767,7 @@
 	public void test0083() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0083", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1797,7 +1797,7 @@
 	public void test0084() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0084", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1829,7 +1829,7 @@
 	public void test0085() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0085", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1856,7 +1856,7 @@
 	public void test0086() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0086", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1880,7 +1880,7 @@
 	public void test0087() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0087", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -1899,7 +1899,7 @@
 	public void test0088() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0088", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1919,7 +1919,7 @@
 	public void test0089() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0089", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1947,7 +1947,7 @@
 	public void test0090() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0090", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 
@@ -1970,7 +1970,7 @@
 	public void test0091() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0091", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		MethodDeclaration method = (MethodDeclaration)((TypeDeclaration) ((CompilationUnit) result).types().get(0)).bodyDeclarations().get(0);
 		SingleVariableDeclaration node = (SingleVariableDeclaration) method.parameters().get(0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
@@ -1987,7 +1987,7 @@
 	public void test0092() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0092", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		MethodDeclaration method = (MethodDeclaration)((TypeDeclaration) ((CompilationUnit) result).types().get(0)).bodyDeclarations().get(0);
 		SingleVariableDeclaration node = (SingleVariableDeclaration) method.parameters().get(0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
@@ -2006,7 +2006,7 @@
 	public void test0093() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0093", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		ForStatement forStatement = (ForStatement) node;
 		BreakStatement statement = (BreakStatement) ((Block) forStatement.getBody()).statements().get(0);
@@ -2022,7 +2022,7 @@
 	public void test0094() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0094", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		ForStatement forStatement = (ForStatement) node;
 		ContinueStatement statement = (ContinueStatement) ((Block) forStatement.getBody()).statements().get(0);
@@ -2038,7 +2038,7 @@
 	public void test0095() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0095", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		LabeledStatement labeledStatement = (LabeledStatement) getASTNode((CompilationUnit) result, 0, 0, 0);
 		ForStatement forStatement = (ForStatement) labeledStatement.getBody();
 		ContinueStatement statement = (ContinueStatement) ((Block) forStatement.getBody()).statements().get(0);
@@ -2055,7 +2055,7 @@
 	public void test0096() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0096", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		LabeledStatement labeledStatement = (LabeledStatement) getASTNode((CompilationUnit) result, 0, 0, 0);
 		ForStatement forStatement = (ForStatement) labeledStatement.getBody();
 		BreakStatement statement = (BreakStatement) ((Block) forStatement.getBody()).statements().get(0);
@@ -2072,7 +2072,7 @@
 	public void test0097() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0097", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		SwitchStatement switchStatement = this.ast.newSwitchStatement();
@@ -2136,7 +2136,7 @@
 	public void test0098() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0098", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		EmptyStatement emptyStatement = this.ast.newEmptyStatement();
@@ -2150,7 +2150,7 @@
 	public void test0099() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0099", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		DoStatement doStatement = this.ast.newDoStatement();
@@ -2170,7 +2170,7 @@
 	public void test0100() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0100", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		WhileStatement whileStatement = this.ast.newWhileStatement();
@@ -2186,7 +2186,7 @@
 	public void test0101() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0101", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		WhileStatement whileStatement = this.ast.newWhileStatement();
@@ -2202,7 +2202,7 @@
 	public void test0102() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0102", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2226,7 +2226,7 @@
 	public void test0103() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0103", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2253,7 +2253,7 @@
 	public void test0104() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0104", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2280,7 +2280,7 @@
 	public void test0105() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0105", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2307,7 +2307,7 @@
 	public void test0106() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0106", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2343,7 +2343,7 @@
 	public void test0107() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0107", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2370,7 +2370,7 @@
 	public void test0108() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0108", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2397,7 +2397,7 @@
 	public void test0109() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0109", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		InfixExpression infixExpression = this.ast.newInfixExpression();
@@ -2433,7 +2433,7 @@
 	public void test0110() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0110", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ReturnStatement returnStatement = this.ast.newReturnStatement();
@@ -2450,7 +2450,7 @@
 	public void test0111() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0111", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ReturnStatement returnStatement = this.ast.newReturnStatement();
@@ -2467,7 +2467,7 @@
 	public void test0112() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0112", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		SynchronizedStatement synchronizedStatement = this.ast.newSynchronizedStatement();
@@ -2485,7 +2485,7 @@
 	public void test0113() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0113", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		TryStatement tryStatement = this.ast.newTryStatement();
@@ -2512,7 +2512,7 @@
 	public void test0114() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0114", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		TryStatement tryStatement = this.ast.newTryStatement();
@@ -2537,7 +2537,7 @@
 	public void test0115() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0115", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		TryStatement tryStatement = this.ast.newTryStatement();
@@ -2569,7 +2569,7 @@
 	public void test0116() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0116", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ThrowStatement throwStatement = this.ast.newThrowStatement();
@@ -2584,7 +2584,7 @@
 	public void test0117() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0117", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ThrowStatement throwStatement = this.ast.newThrowStatement();
@@ -2599,7 +2599,7 @@
 	public void test0118() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0118", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ThrowStatement throwStatement = this.ast.newThrowStatement();
@@ -2614,7 +2614,7 @@
 	public void test0119() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0119", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		IfStatement ifStatement = this.ast.newIfStatement();
@@ -2630,7 +2630,7 @@
 	public void test0120() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0120", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		IfStatement ifStatement = this.ast.newIfStatement();
@@ -2649,7 +2649,7 @@
 	public void test0121() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0121", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		IfStatement ifStatement = this.ast.newIfStatement();
@@ -2668,7 +2668,7 @@
 	public void test0122() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0122", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		IfStatement ifStatement = this.ast.newIfStatement();
@@ -2688,7 +2688,7 @@
 	public void test0123() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0123", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		IfStatement ifStatement = this.ast.newIfStatement();
@@ -2715,7 +2715,7 @@
 	public void test0124() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0124", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment fragment = this.ast.newVariableDeclarationFragment();
@@ -2758,7 +2758,7 @@
 	public void test0125() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0125", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		VariableDeclarationFragment fragment = this.ast.newVariableDeclarationFragment();
@@ -2801,7 +2801,7 @@
 	public void test0126() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0126", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -2830,7 +2830,7 @@
 	public void test0127() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0127", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -2859,7 +2859,7 @@
 	public void test0128() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0128", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -2888,7 +2888,7 @@
 	public void test0129() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0129", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -2909,7 +2909,7 @@
 	public void test0130() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0130", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -2954,7 +2954,7 @@
 	public void test0131() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0131", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -2978,7 +2978,7 @@
 	public void test0132() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0132", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -2993,7 +2993,7 @@
 	public void test0133() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0133", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -3008,7 +3008,7 @@
 	public void test0134() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0134", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -3024,7 +3024,7 @@
 	public void test0135() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0135", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -3038,7 +3038,7 @@
 	public void test0136() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0136", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -3053,7 +3053,7 @@
 	public void test0137() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0137", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -3068,7 +3068,7 @@
 	public void test0138() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0138", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3086,7 +3086,7 @@
 	public void test0139() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0139", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3105,7 +3105,7 @@
 	public void test0140() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0140", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3126,7 +3126,7 @@
 	public void test0141() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0141", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3144,7 +3144,7 @@
 	public void test0142() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0142", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3159,7 +3159,7 @@
 	public void test0143() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0143", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3174,7 +3174,7 @@
 	public void test0144() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0144", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3189,7 +3189,7 @@
 	public void test0145() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0145", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		checkSourceRange(node, "{}", source); //$NON-NLS-1$
@@ -3201,7 +3201,7 @@
 	public void test0146() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0146", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		checkSourceRange(node, "static {}", source); //$NON-NLS-1$
@@ -3214,7 +3214,7 @@
 	public void test0147() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0147", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -3234,7 +3234,7 @@
 	public void test0148() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0148", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -3253,7 +3253,7 @@
 	public void test0149() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0149", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -3266,7 +3266,7 @@
 	 */
 	public void test0150() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0150", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -3282,7 +3282,7 @@
 	 */
 	public void test0151() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0151", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The compilation unit is malformed", !isMalformed(result)); //$NON-NLS-1$
 	}
@@ -3292,7 +3292,7 @@
 	 */
 	public void test0152() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0152", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The compilation unit is malformed", !isMalformed(result)); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
@@ -3311,7 +3311,7 @@
 	 */
 	public void test0153() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0153", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The compilation unit is malformed", !isMalformed(result)); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3325,7 +3325,7 @@
 	 */
 	public void test0154() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0154", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3344,7 +3344,7 @@
 	public void test0155() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0155", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit);  //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3366,7 +3366,7 @@
 	public void test0156() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0156", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit);  //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3389,7 +3389,7 @@
 	 */
 	public void test0157() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "Test0157.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3427,7 +3427,7 @@
 	 */
 	public void test0158() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "Test0158.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3465,7 +3465,7 @@
 	 */
 	public void test0159() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0159", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 	}
@@ -3475,7 +3475,7 @@
 	 */
 	public void test0160() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0160", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3536,7 +3536,7 @@
 	 */
 	public void test0161() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0161", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3595,7 +3595,7 @@
 	 */
 	public void test0162() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0162", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3631,7 +3631,7 @@
 	 */
 	public void test0163() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0163", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		assertTrue("Not an anonymous type declaration", expression instanceof ClassInstanceCreation); //$NON-NLS-1$
@@ -3666,7 +3666,7 @@
 	 */
 	public void test0164() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0164", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Not an type declaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -3700,7 +3700,7 @@
 	 */
 	public void test0165() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0165", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Not an type declaration", node instanceof TypeDeclarationStatement); //$NON-NLS-1$
@@ -3736,7 +3736,7 @@
 	 */
 	public void test0166() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0166", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("Not a VariableDeclarationStatement", node instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node;
@@ -3806,7 +3806,7 @@
 	public void test0167() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0167", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Instance of VariableDeclarationStatement", node instanceof VariableDeclarationStatement); //$NON-NLS-1$
@@ -3825,7 +3825,7 @@
 	 */
 	public void test0168() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0168.test1", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3852,7 +3852,7 @@
 	 */
 	public void test0169() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0169", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3878,7 +3878,7 @@
 	 */
 	public void test0170() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "Test0170.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3903,7 +3903,7 @@
 	 */
 	public void test0171() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0171", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -3936,7 +3936,7 @@
 	 */
 	public void test0172() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0172", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -4043,7 +4043,7 @@
 	 */
 	public void test0173() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0173", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Not an expressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$
@@ -4073,7 +4073,7 @@
 	 */
 	public void test0174() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0174", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Not an expressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$
@@ -4102,7 +4102,7 @@
 	 */
 	public void test0175() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0175", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof FieldDeclaration); //$NON-NLS-1$
 		FieldDeclaration fieldDeclaration = (FieldDeclaration) node2;
@@ -4122,7 +4122,7 @@
 	 */
 	public void test0176() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0176", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertTrue("Return statement", node2 instanceof ReturnStatement); //$NON-NLS-1$
 		ReturnStatement returnStatement = (ReturnStatement) node2;
@@ -4145,7 +4145,7 @@
 	 */
 	public void test0177() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0177", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 1, 1);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("Not an expressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$
@@ -4175,7 +4175,7 @@
 	 */
 	public void test0178() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0178", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 1, 0, 0);
 		assertTrue("Return statement", node2 instanceof ReturnStatement); //$NON-NLS-1$
 		ReturnStatement returnStatement = (ReturnStatement) node2;
@@ -4193,7 +4193,7 @@
 	 */
 	public void test0179() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0179", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4212,7 +4212,7 @@
 	 */
 	public void test0180() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0180", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4233,7 +4233,7 @@
 	 */
 	public void test0181() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0181", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4254,7 +4254,7 @@
 	public void test0182() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0182", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement ifStatement = (IfStatement) node2;
@@ -4272,7 +4272,7 @@
 	public void test0183() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0183", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement ifStatement = (IfStatement) node2;
@@ -4290,7 +4290,7 @@
 	public void test0184() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0184", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement ifStatement = (IfStatement) node2;
@@ -4308,7 +4308,7 @@
 	public void test0185() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0185", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement ifStatement = (IfStatement) node2;
@@ -4326,7 +4326,7 @@
 	public void test0186() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0186", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement ifStatement = (IfStatement) node2;
@@ -4344,7 +4344,7 @@
 	public void test0187() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0187", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("IfStatement", node2 instanceof WhileStatement); //$NON-NLS-1$
 		WhileStatement whileStatement = (WhileStatement) node2;
@@ -4362,7 +4362,7 @@
 	public void test0188() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0188", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 2);
 		assertTrue("DoStatement", node2 instanceof DoStatement); //$NON-NLS-1$
 		DoStatement statement = (DoStatement) node2;
@@ -4380,7 +4380,7 @@
 	public void test0189() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0189", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("ForStatement", node2 instanceof ForStatement); //$NON-NLS-1$
 		ForStatement statement = (ForStatement) node2;
@@ -4398,7 +4398,7 @@
 	public void test0190() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0190", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 2, 1);
 		assertTrue("IfStatement", node2 instanceof IfStatement); //$NON-NLS-1$
 		IfStatement statement = (IfStatement) node2;
@@ -4416,7 +4416,7 @@
 	public void test0191() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0191", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -4440,7 +4440,7 @@
 	public void test0192() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0192", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4461,7 +4461,7 @@
 	public void test0193() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0193", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4483,7 +4483,7 @@
 	public void test0194() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0194", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4506,7 +4506,7 @@
 	public void test0195() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0195", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 1, 0, 1);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -4530,7 +4530,7 @@
 	public void test0196() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0196", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 2);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -4551,7 +4551,7 @@
 	public void test0197() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0197", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType());
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 0);
@@ -4577,7 +4577,7 @@
 	public void test0198() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0198", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("ReturnStatement", node2 instanceof ReturnStatement); //$NON-NLS-1$
 		ReturnStatement returnStatement = (ReturnStatement) node2;
@@ -4603,7 +4603,7 @@
 	public void test0199() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0199", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4632,7 +4632,7 @@
 	public void test0200() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0200", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 1, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -4662,7 +4662,7 @@
 	public void test0201() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0201", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertTrue("ForStatement", node2 instanceof ForStatement); //$NON-NLS-1$
 		ForStatement forStatement = (ForStatement) node2;
@@ -4678,7 +4678,7 @@
 	public void test0202() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0202", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("FieldDeclaration", node2 instanceof FieldDeclaration); //$NON-NLS-1$
 		FieldDeclaration fieldDeclaration = (FieldDeclaration) node2;
@@ -4700,7 +4700,7 @@
 	public void test0203() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0203", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("FieldDeclaration", node2 instanceof FieldDeclaration); //$NON-NLS-1$
 		FieldDeclaration fieldDeclaration = (FieldDeclaration) node2;
@@ -4726,7 +4726,7 @@
 	public void test0204() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0204", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("FieldDeclaration", node2 instanceof FieldDeclaration); //$NON-NLS-1$
 		FieldDeclaration fieldDeclaration = (FieldDeclaration) node2;
@@ -4760,7 +4760,7 @@
 	public void test0205() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0205", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("TypeDeclarationStatement", node2 instanceof TypeDeclarationStatement); //$NON-NLS-1$
 		TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) node2;
@@ -4848,7 +4848,7 @@
 	public void test0207() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0207", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -4863,7 +4863,7 @@
 	public void test0208() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0208", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -4878,7 +4878,7 @@
 	public void test0209() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0209", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
@@ -4894,7 +4894,7 @@
 	public void test0210() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0210", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -4908,7 +4908,7 @@
 	public void test0211() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0211", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -4923,7 +4923,7 @@
 	public void test0212() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0212", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a FieldDeclaration", node instanceof FieldDeclaration); //$NON-NLS-1$
@@ -4938,7 +4938,7 @@
 	public void test0213() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0213", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -4956,7 +4956,7 @@
 	public void test0214() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0214", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -4975,7 +4975,7 @@
 	public void test0215() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0215", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -4996,7 +4996,7 @@
 	public void test0216() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0216", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -5014,7 +5014,7 @@
 	public void test0217() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0217", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -5029,7 +5029,7 @@
 	public void test0218() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0218", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -5044,7 +5044,7 @@
 	public void test0219() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0219", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		assertTrue("The node is not a TypeDeclaration", node instanceof TypeDeclaration); //$NON-NLS-1$
@@ -5059,7 +5059,7 @@
 	public void test0220() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0220", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		checkSourceRange(node, "{}", source); //$NON-NLS-1$
@@ -5071,7 +5071,7 @@
 	public void test0221() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0221", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		checkSourceRange(node, "static {}", source); //$NON-NLS-1$
@@ -5084,7 +5084,7 @@
 	public void test0222() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0222", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -5104,7 +5104,7 @@
 	public void test0223() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0223", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -5123,7 +5123,7 @@
 	public void test0224() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0224", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		Javadoc actualJavadoc = ((Initializer) node).getJavadoc();
@@ -5137,7 +5137,7 @@
 	public void test0225() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0225", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		LabeledStatement labeledStatement = (LabeledStatement) getASTNode((CompilationUnit) result, 0, 0, 0);
 		checkSourceRange(labeledStatement.getLabel(), "label", source); //$NON-NLS-1$
 		ForStatement forStatement = (ForStatement) labeledStatement.getBody();
@@ -5156,7 +5156,7 @@
 	public void test0226() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0226", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		LabeledStatement labeledStatement = (LabeledStatement) getASTNode((CompilationUnit) result, 0, 0, 0);
 		checkSourceRange(labeledStatement.getLabel(), "label", source); //$NON-NLS-1$
 		ForStatement forStatement = (ForStatement) labeledStatement.getBody();
@@ -5175,7 +5175,7 @@
 	public void test0227() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0227", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 3, 2, 0);
 		assertTrue("ReturnStatement", node2 instanceof ReturnStatement); //$NON-NLS-1$
 		ReturnStatement returnStatement = (ReturnStatement) node2;
@@ -5262,7 +5262,7 @@
 	public void test0228() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0228", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertTrue("ReturnStatement", node2 instanceof ReturnStatement); //$NON-NLS-1$
 		ReturnStatement returnStatement = (ReturnStatement) node2;
@@ -5290,7 +5290,7 @@
 	public void test0229() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0229", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -5320,7 +5320,7 @@
 	public void test0230() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0230", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 1, 0);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -5345,7 +5345,7 @@
 	public void test0231() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0231", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("ExpressionStatement", node2 instanceof ExpressionStatement); //$NON-NLS-1$
 		ExpressionStatement expressionStatement = (ExpressionStatement) node2;
@@ -5380,7 +5380,7 @@
 	 */
 	public void test0232() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0232", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node2 = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertTrue("VariableDeclarationStatement", node2 instanceof VariableDeclarationStatement); //$NON-NLS-1$
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) node2;
@@ -5411,7 +5411,7 @@
 	 */
 	public void test0233() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0233", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("Expression should not be null", result); //$NON-NLS-1$
 		assertTrue("The compilation unit is malformed", !isMalformed(result)); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
@@ -5427,7 +5427,7 @@
 	 */
 	public void test0234() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0234", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true, true);
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("The fiels is not malformed", !isMalformed(node)); //$NON-NLS-1$
@@ -5449,7 +5449,7 @@
 	 */
 	public void test0234_2() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0234", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true, false);
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("The fiels is not malformed", !isMalformed(node)); //$NON-NLS-1$
@@ -5470,7 +5470,7 @@
 	 */
 	public void test0235() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0235", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertTrue("The fiels is not malformed", !isMalformed(node)); //$NON-NLS-1$
@@ -5491,7 +5491,7 @@
 	 */
 	public void test0237() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "junit.framework", "TestCase.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 	}
@@ -5501,7 +5501,7 @@
 	 */
 	public void test0238() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0238", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
@@ -5536,7 +5536,7 @@
 	 */
 	public void test0239() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0239", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0, 0);
@@ -5574,7 +5574,7 @@
 	 */
 	public void test0240() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0240", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5615,7 +5615,7 @@
 	 */
 	public void test0241() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0241", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0);
@@ -5651,7 +5651,7 @@
 	 */
 	public void test0242() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0242", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0, 0);
@@ -5694,7 +5694,7 @@
 	public void test0243() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0243", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5713,7 +5713,7 @@
 	public void test0244() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0244", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5732,7 +5732,7 @@
 	 */
 	public void test0245() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0245", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -5758,7 +5758,7 @@
 	public void test0246() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0246", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -5786,7 +5786,7 @@
 	public void test0247() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0247", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -5803,7 +5803,7 @@
 	 */
 	public void test0248() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0248", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -5826,7 +5826,7 @@
 	 */
 	public void test0249() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0249", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 2, 1);
@@ -5854,7 +5854,7 @@
 	 */
 	public void test0250() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0250", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -5878,7 +5878,7 @@
 	public void test0251() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0251", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5908,7 +5908,7 @@
 	 */
 	public void test0252() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0252", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
@@ -5930,7 +5930,7 @@
 	 */
 	public void test0253() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0253", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5951,7 +5951,7 @@
 	 */
 	public void test0254() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0254", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 1, 0);
@@ -5971,7 +5971,7 @@
 	 */
 	public void test0255() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0255", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -5996,7 +5996,7 @@
 	 */
 	public void test0256() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0256", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -6027,7 +6027,7 @@
 	 */
 	public void test0257() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0257", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -6052,7 +6052,7 @@
 	 */
 	public void test0258() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0258", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -6083,7 +6083,7 @@
 	 */
 	public void test0259() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0259", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 	}
@@ -6093,7 +6093,7 @@
 	 */
 	public void test0260() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0260", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -6122,7 +6122,7 @@
 	 */
 	public void test0261() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0261", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6141,7 +6141,7 @@
 	 */
 	public void test0262() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0262", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6171,7 +6171,7 @@
 	 */
 	public void test0263() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0263", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6196,7 +6196,7 @@
 	public void test0264() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0264", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6231,7 +6231,7 @@
 	 */
 	public void test0265() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0265", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 	}
@@ -6242,7 +6242,7 @@
 	public void test0266() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0266", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6269,7 +6269,7 @@
 	public void test0267() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0267", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6296,7 +6296,7 @@
 	public void test0268() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0268", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6322,7 +6322,7 @@
 	public void test0269() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0269", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6348,7 +6348,7 @@
 	public void test0270() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0270", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6370,7 +6370,7 @@
 	public void test0271() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0271", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6396,7 +6396,7 @@
 	public void test0272() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0272", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6414,7 +6414,7 @@
 	public void test0273() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0273", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6438,7 +6438,7 @@
 	public void test0274() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0274", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6462,7 +6462,7 @@
 	public void test0275() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0275", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6480,7 +6480,7 @@
 	public void test0276() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0276", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6505,7 +6505,7 @@
 	public void test0277() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0277", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6528,7 +6528,7 @@
 	public void test0278() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0278", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6552,7 +6552,7 @@
 	public void test0279() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0279", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6576,7 +6576,7 @@
 	 */
 	public void test0280() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0280", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		AST newAst = result.getAST();
@@ -6663,7 +6663,7 @@
 	public void test0281() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0281", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6684,7 +6684,7 @@
 	public void test0282() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0282", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6705,7 +6705,7 @@
 	public void test0283() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0283", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6726,7 +6726,7 @@
 	public void test0284() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0284", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6747,7 +6747,7 @@
 	public void test0285() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0285", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6768,7 +6768,7 @@
 	public void test0286() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0286", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6789,7 +6789,7 @@
 	public void test0287() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0287", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6810,7 +6810,7 @@
 	public void test0288() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0288", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6831,7 +6831,7 @@
 	public void test0289() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0289", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6852,7 +6852,7 @@
 	public void test0290() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0290", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6872,7 +6872,7 @@
 	 */
 	public void test0291() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0291", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -6885,7 +6885,7 @@
 	 */
 	public void test0292() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0292", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6917,7 +6917,7 @@
 	public void test0293() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0293", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6953,7 +6953,7 @@
 	public void test0294() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0294", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -6984,7 +6984,7 @@
 	 */
 	public void test0295() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0295", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7009,7 +7009,7 @@
 	public void test0296() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0296", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7040,7 +7040,7 @@
 	 */
 	public void test0297() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0297", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		runConversion(AST.JLS8, sourceUnit, false);
+		runConversion(getJLS8(), sourceUnit, false);
 	}
 
 	/**
@@ -7049,7 +7049,7 @@
 	public void test0298() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0298", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7067,7 +7067,7 @@
 	public void test0299() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0299", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7092,7 +7092,7 @@
 	public void test0300() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0300", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7114,7 +7114,7 @@
 	public void test0301() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0301", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7135,7 +7135,7 @@
 	public void test0302() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0302", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7154,7 +7154,7 @@
 	 */
 	public void test0303() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0303", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7182,7 +7182,7 @@
 	public void test0304() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0304", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7205,7 +7205,7 @@
 				"	public void foo(int arg) {}\n" +  //$NON-NLS-1$
 				"}").toCharArray(); //$NON-NLS-1$
 		IJavaProject project = getJavaProject("Converter"); //$NON-NLS-1$
-		ASTNode result = runConversion(AST.JLS8, source, "Test.java", project, true); //$NON-NLS-1$
+		ASTNode result = runConversion(getJLS8(), source, "Test.java", project, true); //$NON-NLS-1$
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7230,7 +7230,7 @@
 				"	public void foo(int arg) {}\n" +  //$NON-NLS-1$
 				"}").toCharArray(); //$NON-NLS-1$
 		IJavaProject project = getJavaProject("Converter"); //$NON-NLS-1$
-		ASTNode result = runConversion(AST.JLS8, source, "Object.java", project, true); //$NON-NLS-1$
+		ASTNode result = runConversion(getJLS8(), source, "Object.java", project, true); //$NON-NLS-1$
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7251,7 +7251,7 @@
 	public void test0307() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0307", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7272,7 +7272,7 @@
 	 */
 	public void test0308() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0308", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7297,7 +7297,7 @@
 	 */
 	public void test0309() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0309", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7320,7 +7320,7 @@
 	 */
 	public void test0310() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0310", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7345,7 +7345,7 @@
 	public void test0311() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0311", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7394,7 +7394,7 @@
 	public void test0312() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0312", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7439,7 +7439,7 @@
 	public void test0313() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0313", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7470,7 +7470,7 @@
 	public void test0314() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0314", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No result", result); //$NON-NLS-1$
 		assertTrue("Not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7487,7 +7487,7 @@
 	public void test0315() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0315", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7523,7 +7523,7 @@
 	 */
 	public void test0316() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "Hello.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No result", result); //$NON-NLS-1$
 		assertTrue("Not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7536,7 +7536,7 @@
 	 */
 	public void test0317() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0317", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7574,7 +7574,7 @@
 	 */
 	public void test0318() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0318", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
@@ -7587,7 +7587,7 @@
 	 */
 	public void test0319() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0319", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7621,7 +7621,7 @@
 	public void test0320() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0320", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7646,7 +7646,7 @@
 	public void test0321() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0321", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7672,7 +7672,7 @@
 	 */
 	public void test0322() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0322", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7696,7 +7696,7 @@
 	 */
 	public void test0323() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0323", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7723,7 +7723,7 @@
 	 */
 	public void test0324() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0324", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7750,7 +7750,7 @@
 	 */
 	public void test0325() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0325", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7777,7 +7777,7 @@
 	 */
 	public void test0326() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0326", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
@@ -7794,7 +7794,7 @@
 	 */
 	public void test0327() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0327", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7823,7 +7823,7 @@
 	public void test0328() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0328", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7864,7 +7864,7 @@
 	public void test0329() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0329", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7904,7 +7904,7 @@
 	 */
 	public void test0330() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0330", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7937,7 +7937,7 @@
 	 */
 	public void test0331() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0331", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7964,7 +7964,7 @@
 	 */
 	public void test0332() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0332", "LocalSelectionTransfer.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 	}
@@ -7974,7 +7974,7 @@
 	 */
 	public void test0333() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0333", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8012,7 +8012,7 @@
 	public void test0334() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0334", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8052,7 +8052,7 @@
 	 */
 	public void test0335() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0335", "ExceptionTestCaseTest.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8086,7 +8086,7 @@
 	 */
 	public void test0336() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0336", "SorterTest.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8119,7 +8119,7 @@
 	public void test0337() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0337", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8140,7 +8140,7 @@
 	 */
 	public void test0338() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0338", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8150,7 +8150,7 @@
 		assertTrue("not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
 		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
 		IBinding binding;
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < getJLS8()) {
 			List thrownExceptions = internalThrownExceptions(methodDeclaration);
 			assertEquals("Wrong size", 1, thrownExceptions.size()); //$NON-NLS-1$
 			Name name = (Name) thrownExceptions.get(0);
@@ -8171,7 +8171,7 @@
 	public void test0339() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0339", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8207,7 +8207,7 @@
 	 */
 	public void test0340() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "p3", "B.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8262,7 +8262,7 @@
 	public void test0341() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0341", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8380,7 +8380,7 @@
 	public void test0343() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0343", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8411,7 +8411,7 @@
 			project.setOption(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
 			project.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
 			project.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_4);
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			assertNotNull("No compilation unit", result); //$NON-NLS-1$
 			assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 			CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8430,7 +8430,7 @@
 	 */
 	public void test0345() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0345", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8484,7 +8484,7 @@
 	public void test0346() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0346", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8520,7 +8520,7 @@
 	public void test0347() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0347", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8546,7 +8546,7 @@
 	public void test0348() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0348", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8572,7 +8572,7 @@
 	public void test0349() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0349", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8598,7 +8598,7 @@
 	public void test0350() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0350", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8624,7 +8624,7 @@
 	public void test0351() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0351", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8657,7 +8657,7 @@
 	public void test0352() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0352", "Test2.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8690,7 +8690,7 @@
 	public void test0353() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0353", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8724,7 +8724,7 @@
 	 */
 	public void test0354() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0354", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8736,7 +8736,7 @@
 	 */
 	public void test0355() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0355", "Foo.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8760,7 +8760,7 @@
 	 */
 	public void test0356() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0356", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8793,7 +8793,7 @@
 	public void test0357() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0357", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8812,7 +8812,7 @@
 	public void test0358() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0358", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8831,7 +8831,7 @@
 	public void test0359() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0359", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8849,7 +8849,7 @@
 	 */
 	public void test0360() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0360", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8867,7 +8867,7 @@
 	 */
 	public void test0361() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0361", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8885,7 +8885,7 @@
 	public void test0362() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0362", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		ForStatement forStatement = this.ast.newForStatement();
@@ -8939,7 +8939,7 @@
 	public void test0363() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0363", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8963,7 +8963,7 @@
 	public void test0364() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0364", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -8986,7 +8986,7 @@
 	 */
 	public void test0365() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0365", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9012,7 +9012,7 @@
 	public void test0366() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0366", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9033,7 +9033,7 @@
 	public void test0367() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0367", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9054,7 +9054,7 @@
 	public void test0368() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0368", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9075,7 +9075,7 @@
 	public void test0369() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0369", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9096,7 +9096,7 @@
 	public void test0370() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0370", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull("Expression should not be null", node); //$NON-NLS-1$
 		DoStatement doStatement = this.ast.newDoStatement();
@@ -9117,7 +9117,7 @@
 	public void test0371() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0371", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9138,7 +9138,7 @@
 	public void test0372() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0372", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9159,7 +9159,7 @@
 	public void test0373() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0373", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9185,7 +9185,7 @@
 	public void test0374() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0374", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9210,7 +9210,7 @@
 	 */
 	public void test0375() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0375", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9229,7 +9229,7 @@
 	public void test0376() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0376", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9252,7 +9252,7 @@
 	 */
 	public void test0377() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0377", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9275,7 +9275,7 @@
 	public void test0378() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0378", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9294,7 +9294,7 @@
 	public void test0379() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0379", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode expression = getASTNodeToCompare((CompilationUnit) result);
 		assertNotNull("Expression should not be null", expression); //$NON-NLS-1$
 		assertTrue("Not a class instance creation", expression.getNodeType() == ASTNode.CLASS_INSTANCE_CREATION);		//$NON-NLS-1$
@@ -9308,7 +9308,7 @@
 	 */
 	public void test0380() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0380", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9336,7 +9336,7 @@
 	 */
 	public void test0381() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0381", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9354,7 +9354,7 @@
 	 */
 	public void test0382() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0382", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9372,7 +9372,7 @@
 	 */
 	public void test0383() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0383", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9390,7 +9390,7 @@
 	 */
 	public void test0384() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0384", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9408,7 +9408,7 @@
 	 */
 	public void test0385() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0385", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9421,7 +9421,7 @@
 	public void test0386() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0386", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9446,7 +9446,7 @@
 	public void test0387() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0387", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9469,7 +9469,7 @@
 	 */
 	public void test0388() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0388", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9488,7 +9488,7 @@
 	 */
 	public void test0389() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0389", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9507,7 +9507,7 @@
 	 */
 	public void test0390() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0390", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9527,7 +9527,7 @@
 	 */
 	public void test0391() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0391", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9547,7 +9547,7 @@
 	 */
 	public void test0392() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0392", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9568,7 +9568,7 @@
 	public void test0393() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0393", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9600,7 +9600,7 @@
 	public void test0394() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0394", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9624,7 +9624,7 @@
 	public void test0395() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0395", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -9654,7 +9654,7 @@
 	public void test0396() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0396", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
@@ -9688,7 +9688,7 @@
 	public void test0397() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0397", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
@@ -9720,7 +9720,7 @@
 	public void test0398() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0398", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a variable declaration statement", node.getNodeType() == ASTNode.VARIABLE_DECLARATION_STATEMENT); //$NON-NLS-1$
@@ -9745,7 +9745,7 @@
 	 */
 	public void test0399() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0399", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
@@ -9762,7 +9762,7 @@
 	public void test0400() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0400", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
@@ -9778,7 +9778,7 @@
 	
 	public void test0401() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter18" , "src", "testBug496596", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 2, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
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 6b8f9e1..994416c 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,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -53,6 +57,7 @@
 import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.MethodInvocation;
 import org.eclipse.jdt.core.dom.MethodRef;
+import org.eclipse.jdt.core.dom.ModuleDeclaration;
 import org.eclipse.jdt.core.dom.NullLiteral;
 import org.eclipse.jdt.core.dom.NumberLiteral;
 import org.eclipse.jdt.core.dom.PackageDeclaration;
@@ -280,6 +285,14 @@
 		}
 
 		/**
+		 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(ModuleDeclaration)
+		 */
+		public void endVisit(ModuleDeclaration node) {
+/*			IModuleBinding moduleBinding = node.resolveBinding(); //TODO: enable after bug 515875 enables module binding
+			collectBindings(node, moduleBinding);*/
+		}
+
+		/**
 		 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(MethodInvocation)
 		 */
 		public void endVisit(MethodInvocation node) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBugsTestJLS8.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBugsTestJLS8.java
index 1218989..0cc8fc5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBugsTestJLS8.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterBugsTestJLS8.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation and others.
+ * Copyright (c) 2011, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -29,6 +29,9 @@
 @SuppressWarnings("rawtypes")
 public class ASTConverterBugsTestJLS8 extends ASTConverterBugsTest {
 
+/**
+ * @deprecated
+ */
 public ASTConverterBugsTestJLS8(String name) {
     super(name);
     this.testLevel = AST.JLS8;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
index eda547b..e7f0437 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -57,8 +57,9 @@
 	this.buffer.setLength(0);
 }
 
-/*
+/**
  * @see ASTVisitor#visit(ArrayType)
+ * @deprecated
  */
 public boolean visit(ArrayType node) {
 	if (node.getAST().apiLevel() < AST.JLS8) {
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 51ac7c1..b939c9a 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, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8330,7 +8330,7 @@
 		assertTrue("not a MethodDeclaration", node instanceof MethodDeclaration); //$NON-NLS-1$
 		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
 		IBinding binding;
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < getJLS8()) {
 			List thrownExceptions = internalThrownExceptions(methodDeclaration);
 			assertEquals("Wrong size", 1, thrownExceptions.size()); //$NON-NLS-1$
 			Name name = (Name) thrownExceptions.get(0);
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 466c9e8..01dd01a 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
@@ -114,7 +114,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(getJLS8());
 	}
 
 	public ASTConverterTestAST8_2(String name) {
@@ -149,7 +149,7 @@
 	 */
 	public void test0401() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0401", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
@@ -175,7 +175,7 @@
 	public void test0402() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0402", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0, 0);
 		assertEquals("Wrong number of problems", 0, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		assertNotNull(node);
@@ -188,7 +188,7 @@
 	 */
 	public void test0403() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0403", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0, 1);
 		assertEquals("Wrong number of problems", 1, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		assertNotNull(node);
@@ -222,7 +222,7 @@
 	 */
 	public void test0404() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0404", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertEquals("Wrong number of problems", 1, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		assertNotNull(node);
@@ -253,7 +253,7 @@
 	 */
 	public void test0405() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0405", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0, 1);
 		assertEquals("Wrong number of problems", 1, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		assertNotNull(node);
@@ -284,7 +284,7 @@
 	 */
 	public void test0406() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0406", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 1);
 		assertEquals("Wrong number of problems", 1, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
@@ -317,7 +317,7 @@
 	 */
 	public void test0407() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0407", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Wrong number of problems", 0, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		CompilationUnit unit = (CompilationUnit) result;
@@ -348,7 +348,7 @@
 	 */
 	public void test0408() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0408", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Wrong number of problems", 0, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
 		assertNotNull(node);
@@ -382,7 +382,7 @@
 			newOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
 			JavaCore.setOptions(newOptions);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0409", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 			CompilationUnit compilationUnit = (CompilationUnit) result;
 			assertProblemsSize(compilationUnit, 0);
@@ -469,7 +469,7 @@
 	 */
 	public void test0410() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0410", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Wrong number of problems", 0, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull(node);
@@ -486,7 +486,7 @@
 	 */
 	public void test0411() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0411", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Wrong number of problems", 0, ((CompilationUnit) result).getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
 		assertNotNull(node);
@@ -503,7 +503,7 @@
 	 */
 	public void test0412() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0412", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
@@ -533,7 +533,7 @@
 	 */
 	public void test0413() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0413", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
@@ -542,7 +542,7 @@
 		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
 		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
 		IBinding binding;
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < getJLS8()) {
 			List throwsException = internalThrownExceptions(methodDeclaration);
 			assertEquals("wrong size", 2, throwsException.size()); //$NON-NLS-1$
 			Name name = (Name) throwsException.get(0);
@@ -563,7 +563,7 @@
 	 */
 	public void test0414() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0414", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
@@ -589,7 +589,7 @@
 
 		ICompilationUnit sourceUnit2 = getCompilationUnit("Converter" , "src", "test0414", "B.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 
-		result = runConversion(AST.JLS8, sourceUnit2, true);
+		result = runConversion(getJLS8(), sourceUnit2, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit2 = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit2.getProblems().length); //$NON-NLS-1$
@@ -606,7 +606,7 @@
 	public void test0415() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0415", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -628,7 +628,7 @@
 	 */
 	public void test0416() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0416", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -661,7 +661,7 @@
 	 */
 	public void test0417() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0417", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -686,7 +686,7 @@
 	 */
 	public void test0418() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0418", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -707,7 +707,7 @@
 	 */
 	public void test0419() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0419", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -730,7 +730,7 @@
 	public void test0420() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0420", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -757,7 +757,7 @@
 	public void test0421() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0421", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -785,7 +785,7 @@
 	public void test0422() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0422", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -813,7 +813,7 @@
 	public void test0423() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0423", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -840,7 +840,7 @@
 	public void test0424() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0424", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -864,7 +864,7 @@
 	public void test0425() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0425", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -891,7 +891,7 @@
 	 */
 	public void test0426() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0426", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -912,7 +912,7 @@
 	 */
 	public void test0427() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0427", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -937,7 +937,7 @@
 	 */
 	public void test0428() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0428", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -962,7 +962,7 @@
 	 */
 	public void test0429() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0429", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -988,7 +988,7 @@
 	public void test0430() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0430", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1011,7 +1011,7 @@
 	 */
 	public void test0431() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0431", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1032,7 +1032,7 @@
 	 */
 	public void test0432() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0432", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1054,7 +1054,7 @@
 	 */
 	public void test0433() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0433", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1083,7 +1083,7 @@
 	 */
 	public void test0434() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0434", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1107,7 +1107,7 @@
 	 */
 	public void test0435() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0435", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1131,7 +1131,7 @@
 	 */
 	public void test0436() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0436", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 1, "The type A.CInner is not visible"); //$NON-NLS-1$
@@ -1157,7 +1157,7 @@
 	 */
 	public void test0437() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0437", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 1, "The type CInner is not visible"); //$NON-NLS-1$
@@ -1179,7 +1179,7 @@
 	 */
 	public void test0438() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0438", "D.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1195,7 +1195,7 @@
 	 */
 	public void test0439() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0439", "E.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, false, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, false, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1216,7 +1216,7 @@
 	public void test0440() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0440", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -1256,7 +1256,7 @@
 	public void test0441() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0441", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -1284,7 +1284,7 @@
 	public void test0442() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0442", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -1313,7 +1313,7 @@
 	 */
 	public void test0443() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0443", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 3, unit.getProblems().length); //$NON-NLS-1$<
@@ -1337,7 +1337,7 @@
 	 */
 	public void test0444() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0444", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 2, unit.getProblems().length); //$NON-NLS-1$<
@@ -1360,7 +1360,7 @@
 	 */
 	public void test0445() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0445", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$<
@@ -1371,7 +1371,7 @@
 	 */
 	public void test0446() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0446", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 2, unit.getProblems().length); //$NON-NLS-1$<
@@ -1382,7 +1382,7 @@
 	 */
 	public void test0447() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0447", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 3, unit.getProblems().length); //$NON-NLS-1$<
@@ -1393,7 +1393,7 @@
 	 */
 	public void test0448() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0448", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -1412,7 +1412,7 @@
 	 */
 	public void test0449() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0449", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -1430,7 +1430,7 @@
 	 */
 	public void test0450() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0450", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
@@ -1518,7 +1518,7 @@
 	public void test0451() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0451", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 2, unit.getProblems().length); //$NON-NLS-1$
@@ -1535,7 +1535,7 @@
 	 */
 	public void test0452() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "NO_WORKING.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0);
@@ -1551,7 +1551,7 @@
 	 */
 	public void test0453() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0453", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0,0);
@@ -1571,7 +1571,7 @@
 	public void test0454() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0454", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0,1);
@@ -1596,7 +1596,7 @@
 	public void test0455() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0455", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1624,7 +1624,7 @@
 	public void test0456() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0456", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1645,7 +1645,7 @@
 	public void test0457() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0457", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1672,7 +1672,7 @@
 	public void test0458() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0458", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1701,7 +1701,7 @@
 	public void test0459() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0459", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1729,7 +1729,7 @@
 	 */
 	public void test0460() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0460", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertTrue("Has error", compilationUnit.getProblems().length == 0); //$NON-NLS-1$
@@ -1743,7 +1743,7 @@
 	 */
 	public void test0461() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0461", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		char[] source = sourceUnit.getSource().toCharArray();
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -1780,7 +1780,7 @@
 	 */
 	public void test0462() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "", "Test462.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertTrue("Has error", compilationUnit.getProblems().length == 0); //$NON-NLS-1$
@@ -1799,7 +1799,7 @@
 	 */
 	public void test0463() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0463", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		char[] source = sourceUnit.getSource().toCharArray();
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1820,7 +1820,7 @@
 	 */
 	public void test0464() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0464", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
 		assertEquals("No error", 1, compilationUnit.getProblems().length); //$NON-NLS-1$
@@ -1842,7 +1842,7 @@
 	 */
 	public void test0465() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0465", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
@@ -1874,7 +1874,7 @@
 			newOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
 			JavaCore.setOptions(newOptions);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0466", "Assert.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			CompilationUnit compilationUnit = (CompilationUnit) result;
 			char[] source = sourceUnit.getSource().toCharArray();
 			ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1898,7 +1898,7 @@
 			newOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
 			JavaCore.setOptions(newOptions);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0467", "Assert.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			CompilationUnit compilationUnit = (CompilationUnit) result;
 			char[] source = sourceUnit.getSource().toCharArray();
 			ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -1923,7 +1923,7 @@
 	 */
 	public void test0468() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0468", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
@@ -1962,7 +1962,7 @@
 	 */
 	public void test0469() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "codeManipulation", "bug.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 2, 0);
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
@@ -1979,7 +1979,7 @@
 	public void test0470() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0470", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
@@ -2006,7 +2006,7 @@
 	public void test0471() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0471", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 1, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 0);
@@ -2027,7 +2027,7 @@
 	 */
 	public void test0472() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "junit.textui", "ResultPrinter.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 2, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 2);
@@ -2050,7 +2050,7 @@
 
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0473", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 			char[] source = sourceUnit.getSource().toCharArray();
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			CompilationUnit compilationUnit = (CompilationUnit) result;
 			assertEquals("No error", 2, compilationUnit.getProblems().length); //$NON-NLS-1$
 			ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
@@ -2071,7 +2071,7 @@
 	public void test0474() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0474", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
@@ -2095,7 +2095,7 @@
 	public void test0475() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0475", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
@@ -2119,7 +2119,7 @@
 	public void test0476() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0476", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 0, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
@@ -2144,7 +2144,7 @@
 	public void test0477() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0477", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		assertEquals("No error", 1, compilationUnit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(compilationUnit, 0, 1, 0);
@@ -2173,7 +2173,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0);
@@ -2222,7 +2222,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0);
@@ -2261,7 +2261,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -2289,7 +2289,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -2329,7 +2329,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -2367,7 +2367,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -2410,7 +2410,7 @@
 		assertEquals("wrong size", 1, memberTypes.length);
 		IType memberType = memberTypes[0];
 		ISourceRange sourceRange = memberType.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -2441,7 +2441,7 @@
 		assertEquals("wrong size", 1, memberTypes.length);
 		IType memberType = memberTypes[0];
 		ISourceRange sourceRange = memberType.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -2471,7 +2471,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 2);
@@ -2502,7 +2502,7 @@
 		assertEquals("wrong size", 3, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 
@@ -2575,7 +2575,7 @@
 		assertEquals("wrong size", 2, initializers.length);
 		IInitializer init = initializers[1];
 		ISourceRange sourceRange = init.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 
@@ -2639,7 +2639,7 @@
 	 */
 	public void test0489() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0489", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 3, unit.getProblems().length); //$NON-NLS-1$<
@@ -2655,7 +2655,7 @@
 	 */
 	public void test0490() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0490", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2672,7 +2672,7 @@
 			JavaCore.setOptions(newOptions);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0491", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 			char[] source = sourceUnit.getSource().toCharArray();
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 			CompilationUnit unit = (CompilationUnit) result;
 			assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2698,7 +2698,7 @@
 			JavaCore.setOptions(newOptions);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0492", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 			char[] source = sourceUnit.getSource().toCharArray();
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 			assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 			CompilationUnit unit = (CompilationUnit) result;
 			assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2718,7 +2718,7 @@
 	public void test0493() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0493", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2729,7 +2729,7 @@
 		checkSourceRange(type, "Class[][]", source);
 		assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
 		ArrayType arrayType = (ArrayType) type;
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			Type componentType = componentType(arrayType);
 			assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
 			checkSourceRange(componentType, "Class[]", source);
@@ -2749,7 +2749,7 @@
 	public void test0494() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0494", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2760,7 +2760,7 @@
 		checkSourceRange(type, "Class[][][]", source);
 		assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
 		ArrayType arrayType = (ArrayType) type;
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			Type componentType = componentType(arrayType);
 			assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
 			checkSourceRange(componentType, "Class[][]", source);
@@ -2784,7 +2784,7 @@
 	public void test0495() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0495", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2795,7 +2795,7 @@
 		checkSourceRange(type, "Class[][]", source);
 		assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
 		ArrayType arrayType = (ArrayType) type;
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			Type componentType = componentType(arrayType);
 			assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
 			checkSourceRange(componentType, "Class[]", source);
@@ -2819,7 +2819,7 @@
 	public void test0496() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0496", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2830,7 +2830,7 @@
 		checkSourceRange(type, "Class[][][][]", source);
 		assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
 		ArrayType arrayType = (ArrayType) type;
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			Type componentType = componentType(arrayType);
 			assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
 			checkSourceRange(componentType, "Class[][][]", source);
@@ -2858,7 +2858,7 @@
 	public void test0497() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0497", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$<
@@ -2869,7 +2869,7 @@
 		checkSourceRange(type, "Class[]", source);
 		assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
 		ArrayType arrayType = (ArrayType) type;
-		type = this.ast.apiLevel() < AST.JLS8 ? componentType(arrayType) : arrayType.getElementType();
+		type = this.ast.apiLevel() < getJLS8() ? componentType(arrayType) : arrayType.getElementType();
 		assertTrue("is an array type", !type.isArrayType()); //$NON-NLS-1$
 		checkSourceRange(type, "Class", source);
 	}
@@ -2878,7 +2878,7 @@
 	 */
 	public void test0498() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0498", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 	}
 
@@ -2887,7 +2887,7 @@
 	 */
 	public void test0499() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0499", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
@@ -2925,7 +2925,7 @@
 			project.setOption(JavaCore.COMPILER_PB_INVALID_JAVADOC, JavaCore.ERROR);
 			project.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS, JavaCore.ERROR);
 			project.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS, JavaCore.ERROR);
-			CompilationUnit result = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+			CompilationUnit result = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 			IProblem[] problems= result.getProblems();
 			assertTrue(problems.length == 1);
 			assertEquals("Invalid warning", "Javadoc: Missing tag for parameter a", problems[0].getMessage());
@@ -2939,7 +2939,7 @@
 	 */
 	public void test0501() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0501", "JavaEditor.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull(result);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 	}
@@ -2949,7 +2949,7 @@
 	 */
 	public void test0502a() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'i' in initializer
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement)getASTNode(unit, 0, 0, 0);
@@ -2963,7 +2963,7 @@
 	 */
 	public void test0502b() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'j' in 'then' block in initializer
 		IfStatement ifStatement = (IfStatement) getASTNode(unit, 0, 0, 1);
@@ -2979,7 +2979,7 @@
 	 */
 	public void test0502c() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'i' in 'foo()'
 		VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement)getASTNode(unit, 0, 1, 0);
@@ -2993,7 +2993,7 @@
 	 */
 	public void test0502d() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'j' in 'then' block in 'foo()'
 		IfStatement ifStatement = (IfStatement) getASTNode(unit, 0, 1, 1);
@@ -3009,7 +3009,7 @@
 	 */
 	public void test0502e() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'j' in 'else' block in 'foo()'
 		IfStatement ifStatement = (IfStatement) getASTNode(unit, 0, 1, 1);
@@ -3025,7 +3025,7 @@
 	 */
 	public void test0502f() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// first 'new Object(){...}' in 'foo()'
 		ExpressionStatement expressionStatement = (ExpressionStatement) getASTNode(unit, 0, 1, 2);
@@ -3040,7 +3040,7 @@
 	 */
 	public void test0502g() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'B' in 'foo()'
 		TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) getASTNode(unit, 0, 1, 3);
@@ -3054,7 +3054,7 @@
 	 */
 	public void test0502h() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// second 'new Object(){...}' in 'foo()'
 		ExpressionStatement expressionStatement = (ExpressionStatement) getASTNode(unit, 0, 1, 4);
@@ -3069,7 +3069,7 @@
 	 */
 	public void test0502i() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'field' in 'B' in 'foo()'
 		TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) getASTNode(unit, 0, 1, 3);
@@ -3087,7 +3087,7 @@
 	 */
 	public void test0502j() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0502", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// 'bar()' in 'B' in 'foo()'
 		TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) getASTNode(unit, 0, 1, 3);
@@ -3104,7 +3104,7 @@
 	 */
 	public void test0503a() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// top level type A
 		TypeDeclaration type = (TypeDeclaration)getASTNode(unit, 0);
@@ -3117,7 +3117,7 @@
 	 */
 	public void test0503b() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// member type B in A
 		TypeDeclaration type = (TypeDeclaration)getASTNode(unit, 0, 0);
@@ -3130,7 +3130,7 @@
 	 */
 	public void test0503c() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// local type E in foo() in A
 		TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) getASTNode(unit, 0, 1, 0);
@@ -3144,7 +3144,7 @@
 	 */
 	public void test0503d() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// anonymous type new Object() {...} in foo() in A
 		ExpressionStatement expressionStatement = (ExpressionStatement) getASTNode(unit, 0, 1, 1);
@@ -3159,7 +3159,7 @@
 	 */
 	public void test0503e() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// type F in anonymous type new Object() {...} in foo() in A
 		ExpressionStatement expressionStatement = (ExpressionStatement) getASTNode(unit, 0, 1, 1);
@@ -3175,7 +3175,7 @@
 	 */
 	public void test0503f() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// local type C in bar() in B in A
 		MethodDeclaration method = (MethodDeclaration) getASTNode(unit, 0, 0, 0);
@@ -3190,7 +3190,7 @@
 	 */
 	public void test0503g() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// anonymous type new Object() {...} in bar() in B in A
 		MethodDeclaration method = (MethodDeclaration) getASTNode(unit, 0, 0, 0);
@@ -3206,7 +3206,7 @@
 	 */
 	public void test0503h() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// type D in anonymous type new Object() {...} in bar() in B in A
 		MethodDeclaration method = (MethodDeclaration) getASTNode(unit, 0, 0, 0);
@@ -3223,7 +3223,7 @@
 	 */
 	public void test0503i() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0503", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		CompilationUnit unit = (CompilationUnit)runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit unit = (CompilationUnit)runConversion(getJLS8(), sourceUnit, true);
 
 		// unreachable type G in foo() in A
 		IfStatement ifStatement = (IfStatement) getASTNode(unit, 0, 1, 2);
@@ -3240,7 +3240,7 @@
 	public void test0504() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0504", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
@@ -3258,7 +3258,7 @@
 	public void test0505() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0505", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
@@ -3275,7 +3275,7 @@
 	 */
 	public void test0506() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0506", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3295,7 +3295,7 @@
 	 */
 	public void test0507() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0507", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3315,7 +3315,7 @@
 	 */
 	public void test0508() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0508", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 1, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3335,7 +3335,7 @@
 	 */
 	public void test0509() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0509", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3355,7 +3355,7 @@
 	 */
 	public void test0510() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0510", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3375,7 +3375,7 @@
 	 */
 	public void test0511() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0511", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertEquals("Wrong number of problems", 0, (unit).getProblems().length); //$NON-NLS-1$
@@ -3396,7 +3396,7 @@
 	public void test0512() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0512", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0);
 		assertEquals("Wrong number of problems", 2, unit.getProblems().length); //$NON-NLS-1$
@@ -3412,7 +3412,7 @@
 	 */
 	public void test0513() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0513", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 	}
@@ -3423,7 +3423,7 @@
 	 */
 	public void test0514() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0514", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 	}
@@ -3434,7 +3434,7 @@
 	public void test0515() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0515", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0, 0);
@@ -3458,14 +3458,14 @@
 	public void test0516() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0516", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
 		assertNotNull("No node", node);
 		assertTrue("not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION);
 		MethodDeclaration declaration = (MethodDeclaration) node;
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setSource(source);
 		parser.setSourceRange(declaration.getStartPosition(), declaration.getLength());
@@ -3492,7 +3492,7 @@
 	public void test0517() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0517", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		assertNotNull("No comments", unit.getCommentList());
@@ -3501,7 +3501,7 @@
 		assertNotNull("No node", node);
 		assertTrue("not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
 		FieldDeclaration declaration = (FieldDeclaration) node;
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setSource(source);
 		parser.setSourceRange(declaration.getStartPosition(), declaration.getLength());
@@ -3528,14 +3528,14 @@
 	public void test0518() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0518", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
 		assertNotNull("No node", node);
 		assertTrue("not an initializer", node.getNodeType() == ASTNode.INITIALIZER);
 		Initializer declaration = (Initializer) node;
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setSource(source);
 		parser.setSourceRange(declaration.getStartPosition(), declaration.getLength());
@@ -3562,7 +3562,7 @@
 	public void test0519() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0519", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		assertNotNull("No comments", unit.getCommentList());
@@ -3570,7 +3570,7 @@
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertNotNull("No node", node);
 		ASTNode statement = node;
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_STATEMENTS);
 		parser.setSource(source);
 		parser.setSourceRange(statement.getStartPosition(), statement.getLength());
@@ -3597,7 +3597,7 @@
 	public void test0520() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0520", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		assertNotNull("No comments", unit.getCommentList());
@@ -3607,7 +3607,7 @@
 		assertTrue("not a block", node.getNodeType() == ASTNode.EXPRESSION_STATEMENT);
 		ExpressionStatement expressionStatement = (ExpressionStatement) node;
 		Expression expression = expressionStatement.getExpression();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_EXPRESSION);
 		parser.setSource(source);
 		parser.setSourceRange(expression.getStartPosition(), expression.getLength());
@@ -3677,7 +3677,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0);
@@ -3726,7 +3726,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 1, 0);
@@ -3765,7 +3765,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3793,7 +3793,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3832,7 +3832,7 @@
 		assertEquals("wrong size", 2, methods.length);
 		IMethod method = methods[1];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0, 0);
@@ -3870,7 +3870,7 @@
 		assertEquals("wrong size", 1, methods.length);
 		IMethod method = methods[0];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3911,7 +3911,7 @@
 		assertEquals("wrong size", 1, memberTypes.length);
 		IType memberType = memberTypes[0];
 		ISourceRange sourceRange = memberType.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, true);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3940,7 +3940,7 @@
 		assertEquals("wrong size", 1, memberTypes.length);
 		IType memberType = memberTypes[0];
 		ISourceRange sourceRange = memberType.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
@@ -3969,7 +3969,7 @@
 		assertEquals("wrong size", 3, methods.length);
 		IMethod method = methods[2];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		ASTNode node = getASTNode((CompilationUnit) result, 0, 2);
@@ -3998,7 +3998,7 @@
 		assertEquals("wrong size", 5, methods.length);
 		IMethod method = methods[3];
 		ISourceRange sourceRange = method.getSourceRange();
-		ASTNode result = runConversion(AST.JLS8, classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), classFile, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 
@@ -4079,7 +4079,7 @@
 		type = classFile.getType();
 		initializers = type.getInitializers();
 		assertEquals("wrong size", 0, initializers.length);
-		ASTNode result = runConversion(AST.JLS8, classFile, position, false);
+		ASTNode result = runConversion(getJLS8(), classFile, position, false);
 		assertNotNull(result);
 		assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 
@@ -4145,7 +4145,7 @@
 	public void test0533() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0533", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4170,7 +4170,7 @@
 	public void test0534() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0534", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4195,7 +4195,7 @@
 	public void test0535() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0535", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4218,7 +4218,7 @@
 	 */
 	public void test0536() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0536", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result);
 	}
 	/**
@@ -4226,7 +4226,7 @@
 	 */
 	public void test0537a() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0537", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result);
 	}
 	/**
@@ -4234,7 +4234,7 @@
 	 */
 	public void test0537b() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0537", "B.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result);
 	}
 	/**
@@ -4242,7 +4242,7 @@
 	 */
 	public void test0537c() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0537", "C.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertNotNull("No compilation unit", result);
 	}
 	/**
@@ -4262,7 +4262,7 @@
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, false, null, null);
 			assertNotNull("No level 2 compilation unit", unit);
 			assertEquals("Compilation unit has wrong AST level (2)", AST.JLS2, unit.getAST().apiLevel());
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 		} finally {
 			sourceUnit.discardWorkingCopy();
 		}
@@ -4296,7 +4296,7 @@
 			sourceUnit.becomeWorkingCopy(null, null);
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, false, null, null);
 			assertNull("Unexpected compilation unit", unit);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 		} finally {
 			sourceUnit.discardWorkingCopy();
 		}
@@ -4316,7 +4316,7 @@
 				"  Object field;\n" +
 				"}"
 			);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, false, null, null);
 			ASTNode node = getASTNode(unit, 0, 0);
 			assertNotNull("No node", node);
@@ -4340,7 +4340,7 @@
 		try {
 			ReconcilerTests.ProblemRequestor pbRequestor = new ReconcilerTests.ProblemRequestor();
 			sourceUnit.becomeWorkingCopy(pbRequestor, null);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, true/*force pb detection*/, null, null);
 			ASTNode node = getASTNode(unit, 0);
 			assertNotNull("No node", node);
@@ -4375,7 +4375,7 @@
 				"  }\n" +
 				"}"
 			);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, true/*force pb detection*/, null, null);
 			ASTNode node = getASTNode(unit, 0);
 			assertNotNull("No node", node);
@@ -4406,7 +4406,7 @@
 				"}"
 			);
 			sourceUnit.reconcile(ICompilationUnit.NO_AST, false/* don't force pb detection*/, null, null);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, true/*force pb detection*/, null, null);
 			ASTNode node = getASTNode(unit, 0);
 			assertNotNull("No node", node);
@@ -4434,7 +4434,7 @@
 				"  Object field;\n" +
 				"}"
 			);
-			// TODO improve test for AST.JLS8
+			// TODO improve test for getJLS8()
 			CompilationUnit unit = sourceUnit.reconcile(AST.JLS2, false, null, null);
 			assertEquals("Unexpected well known type", null, unit.getAST().resolveWellKnownType("void"));
 		} finally {
@@ -4447,7 +4447,7 @@
 	public void test0539() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0539", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 1, 0);
@@ -4486,7 +4486,7 @@
 		options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
 		options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_4);
 		options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_4);
-		ASTNode result = runConversion(AST.JLS8, source, "Test.java", project, options, true); //$NON-NLS-1$
+		ASTNode result = runConversion(getJLS8(), source, "Test.java", project, options, true); //$NON-NLS-1$
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -4506,7 +4506,7 @@
 	 */
 	public void test0541() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0541", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4535,7 +4535,7 @@
 	public void test0542() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0542", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4703,7 +4703,7 @@
 	 */
 	public void test0543() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0543", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		unit.accept(new GetKeyVisitor());
@@ -4714,7 +4714,7 @@
 	 */
 	public void test0544() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0544", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4731,7 +4731,7 @@
 	 */
 	public void test0545() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0545", "First.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0);
@@ -4741,7 +4741,7 @@
 		assertEquals("Wrong key", "Ltest0545/First$Test;", typeBinding.getKey());
 
 		sourceUnit = getCompilationUnit("Converter", "src", "test0545", "Second.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		result = runConversion(AST.JLS8, sourceUnit, true);
+		result = runConversion(getJLS8(), sourceUnit, true);
 		unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		node = getASTNode(unit, 0, 0);
@@ -4751,7 +4751,7 @@
 		assertEquals("Wrong key", "Ltest0545/Second$Test;", typeBinding.getKey());
 
 		sourceUnit = getCompilationUnit("Converter", "src", "test0545", "Third.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		result = runConversion(AST.JLS8, sourceUnit, true);
+		result = runConversion(getJLS8(), sourceUnit, true);
 		unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		node = getASTNode(unit, 0, 0);
@@ -4762,7 +4762,7 @@
 
 
 		sourceUnit = getCompilationUnit("Converter", "src", "test0545", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		result = runConversion(AST.JLS8, sourceUnit, true);
+		result = runConversion(getJLS8(), sourceUnit, true);
 		unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		node = getASTNode(unit, 0);
@@ -4777,7 +4777,7 @@
 	 */
 	public void test0546() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0546", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 0, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 1, 0, 0);
@@ -4820,7 +4820,7 @@
 	 */
 	public void test0547() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0547", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
 		ASTNode node = getASTNode(unit, 0, 0, 0);
@@ -4845,7 +4845,7 @@
 	 */
 	public void test0548() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0548", "PaletteStackEditPart.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 	}
 
@@ -4854,7 +4854,7 @@
 	 */
 	public void test0549() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0549", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 	}
 
@@ -4863,7 +4863,7 @@
 	 */
 	public void test0550() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0550", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 	}
 
@@ -4873,7 +4873,7 @@
 	public void test0551() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0551", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -4885,7 +4885,7 @@
 	public void test0552() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0552", "Test.java");
 		char[] source = sourceUnit.getSource().toCharArray();
-		CompilationUnit result = (CompilationUnit) runConversion(AST.JLS8, sourceUnit, true);
+		CompilationUnit result = (CompilationUnit) runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Got errors", 0, result.getProblems().length);
 		TypeDeclaration declaration = (TypeDeclaration) result.types().get(0);
 		Block body = declaration.getMethods()[0].getBody();
@@ -4916,7 +4916,7 @@
 	 */
 	public void test0553() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0553", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -4939,7 +4939,7 @@
 	public void test0554() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0554", "B.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -4968,7 +4968,7 @@
 	public void test0555() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0555", "B.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -4997,7 +4997,7 @@
 	public void test0556() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0556", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5022,7 +5022,7 @@
 	public void test0557() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0557", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5066,7 +5066,7 @@
 	public void test0559() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0559", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5094,7 +5094,7 @@
 	public void test0560() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0560", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5122,7 +5122,7 @@
 	public void test0561() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0561", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5150,7 +5150,7 @@
 	public void test0562() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0562", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5178,7 +5178,7 @@
 	public void test0563() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0563", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5205,7 +5205,7 @@
 	public void test0564() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0564", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5232,7 +5232,7 @@
 	public void test0565() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0565", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5259,7 +5259,7 @@
 	public void test0566() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0566", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5275,7 +5275,7 @@
 	public void test0567() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0567", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5290,7 +5290,7 @@
 	 */
 	public void test0568() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0568", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 	}
 
@@ -5299,7 +5299,7 @@
 	 */
 	public void test0570() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0570", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5310,7 +5310,7 @@
 	 * No binding when there is no unit name set
 	 */
 	public void test0571() throws JavaModelException {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		String source = "public class A {public boolean foo() {}}";
 		parser.setSource(source.toCharArray());
 		parser.setProject(getJavaProject("Converter"));
@@ -5327,7 +5327,7 @@
 	 * No binding when there is no unit name set
 	 */
 	public void test0572() throws JavaModelException {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		String source = "public class A {public boolean foo() {}}";
 		parser.setSource(source.toCharArray());
 		parser.setProject(getJavaProject("Converter"));
@@ -5347,7 +5347,7 @@
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0573", "Z.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		String source = sourceUnit.getSource();
 		int pos = source.indexOf("his.ba");
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, pos, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, pos, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		ASTNode node = getASTNode(unit, 0, 0, 0);
@@ -5366,7 +5366,7 @@
 	 */
 	public void test0574() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0574", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5395,7 +5395,7 @@
 	 */
 	public void test0575() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0575", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		final IProblem[] problems = unit.getProblems();
@@ -5432,7 +5432,7 @@
 	 */
 	public void test0578() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0578", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 0);
@@ -6435,7 +6435,7 @@
 	 */
 	public void test0607() throws JavaModelException {
 		final char[] source = "private static Category[] values = new Category[]{v1, v2, v3};".toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setSource(source);
 		ASTNode root = parser.createAST(null);
@@ -6506,7 +6506,7 @@
 	 */
 	public void test0610() throws JavaModelException {
 		final ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0610", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		final ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		final ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 1, "The type Test is deprecated");
@@ -6742,7 +6742,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents.toCharArray());
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			assertProblemsSize(unit, 1, "Dead code");
@@ -6777,7 +6777,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents.toCharArray());
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true);			
+			ASTNode node = runConversion(getJLS8(), workingCopy, true);			
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedOutput = "Dead code";
@@ -6852,13 +6852,13 @@
 	public void test0619() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter", "src", "test0619", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, false);
 		final CompilationUnit unit = (CompilationUnit) result;
 		assertProblemsSize(unit, 0);
 		ASTNode node = getASTNode(unit, 0, 0, 0);
 		assertNotNull("No node", node);
 		ASTNode statement = node;
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_STATEMENTS);
 		parser.setSource(source);
 		parser.setSourceRange(statement.getStartPosition(), statement.getLength());
@@ -7125,7 +7125,7 @@
 				"	public void foo(int arg) {}\n" +  //$NON-NLS-1$
 				"}").toCharArray(); //$NON-NLS-1$
 		IJavaProject project = getJavaProject("Converter"); //$NON-NLS-1$
-		ASTNode result = runConversion(AST.JLS8, source, "Test.java", project); //$NON-NLS-1$
+		ASTNode result = runConversion(getJLS8(), source, "Test.java", project); //$NON-NLS-1$
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7147,7 +7147,7 @@
 				"	public void foo(int arg) {}\n" +  //$NON-NLS-1$
 				"}").toCharArray(); //$NON-NLS-1$
 		IJavaProject project = getJavaProject("Converter"); //$NON-NLS-1$
-		ASTNode result = runConversion(AST.JLS8, source, "Object.java", project); //$NON-NLS-1$
+		ASTNode result = runConversion(getJLS8(), source, "Object.java", project); //$NON-NLS-1$
 		assertNotNull("No compilation unit", result); //$NON-NLS-1$
 		assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
@@ -7222,7 +7222,7 @@
 	 * http://dev.eclipse.org/bugs/show_bug.cgi?id=125270
 	 */
 	public void test0628() throws JavaModelException {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_EXPRESSION);
 		String source = "{\"red\", \"yellow\"}";
 		parser.setSource(source.toCharArray());
@@ -7243,7 +7243,7 @@
 	public void test0629() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0629", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		String expectedOutput =
@@ -7262,7 +7262,7 @@
 	 */
 	public void test0630() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0630", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		String expectedOutput =
@@ -7275,7 +7275,7 @@
 	public void test0631() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0631", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType()); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) result;
 		String expectedOutput =
@@ -7336,7 +7336,7 @@
 	public void test0633() {
 		String src = "switch (state) {case 4:double M0,M1;}";
 		char[] source = src.toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		parser.setSource (source);
 		ASTNode result = parser.createAST (null);
@@ -7380,7 +7380,7 @@
 					"}";
 
 			char[] source = src.toCharArray();
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setKind (ASTParser.K_COMPILATION_UNIT);
 			parser.setSource (source);
 			parser.setStatementsRecovery(true);
@@ -8092,7 +8092,7 @@
 	 */
 	public void test0653() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0653", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, result.getNodeType());
 		CompilationUnit unit = (CompilationUnit) result;
 
@@ -8239,7 +8239,7 @@
 				"        int d;\n" +
 				"    }";
 		char[] source = src.toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		parser.setStatementsRecovery(true);
 		parser.setSource (source);
@@ -8272,7 +8272,7 @@
 				"        int d;\n" +
 				"    }";
 		char[] source = src.toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		parser.setStatementsRecovery(false);
 		parser.setSource (source);
@@ -8333,7 +8333,7 @@
 				"        int d;\n" +
 				"    }";
 		char[] source = src.toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		parser.setStatementsRecovery(true);
 		parser.setSource (source);
@@ -8359,7 +8359,7 @@
 	public void test0659() throws CoreException, JavaModelException {
 		IJavaProject javaProject = createJavaProject("P659", new String[] { "src" }, new String[0], "bin");
 		try {
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setKind(ASTParser.K_COMPILATION_UNIT);
 			parser.setStatementsRecovery(true);
 			parser.setBindingsRecovery(true);
@@ -8961,7 +8961,7 @@
 	 */
 	public void test0669() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0669", "UIPerformChangeOperation.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 		assertNotNull(result);
 	}
 
@@ -8983,7 +8983,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedError =
@@ -9026,7 +9026,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedError =
@@ -9096,7 +9096,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedError =
@@ -9188,7 +9188,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			assertTrue("no binding recovery", unit.getAST().hasBindingsRecovery());
@@ -9254,7 +9254,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			assertProblemsSize(unit, 0);
@@ -9294,7 +9294,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents);
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true, true, true);
+			ASTNode node = runConversion(getJLS8(), workingCopy, true, true, true);
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedError = "Constructor call must be the first statement in a constructor";
@@ -9321,7 +9321,7 @@
 	 */
 	public void test0676() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0676", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true, true, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true, true, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 		CompilationUnit unit = (CompilationUnit) node;
 		assertTrue("no binding recovery", unit.getAST().hasBindingsRecovery());
@@ -9375,7 +9375,7 @@
 	 */
 	public void test0677() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0677", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true);
 		assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType()); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) node;
 		node = getASTNode(unit, 0);
@@ -9409,7 +9409,7 @@
 				"}";
 			workingCopy = getWorkingCopy("/Converter/src/X.java", true/*resolve*/);
 			workingCopy.getBuffer().setContents(contents.toCharArray());
-			ASTNode node = runConversion(AST.JLS8, workingCopy, true);			
+			ASTNode node = runConversion(getJLS8(), workingCopy, true);			
 			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
 			CompilationUnit unit = (CompilationUnit) node;
 			String expectedOutput = "Dead code";
@@ -9495,7 +9495,7 @@
 	 */
 	public void test0680() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0680", "SAMPLE_UTF8.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) node;
 		assertProblemsSize(compilationUnit, 0);
@@ -9512,7 +9512,7 @@
 	 */
 	public void test0681() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "Sample", "Sample.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit compilationUnit = (CompilationUnit) node;
 		assertProblemsSize(compilationUnit, 0);
@@ -9527,7 +9527,7 @@
 	 */
 	public void test0682() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0682", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(
@@ -9555,7 +9555,7 @@
 	 */
 	public void test0683() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0683", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -9572,7 +9572,7 @@
 		ArrayCreation arrayCreation = (ArrayCreation) node;
 		ArrayType arrayType = arrayCreation.getType();
 		checkSourceRange(arrayType, "String[0][b[10]][]", sourceUnit.getSource());
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			node = componentType(arrayType);
 			assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
 			arrayType = (ArrayType)node;
@@ -9592,7 +9592,7 @@
 	 */
 	public void test0684() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0684", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -9617,7 +9617,7 @@
 	 */
 	public void test0685() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0685", "C.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-		ASTNode node = runConversion(AST.JLS8, sourceUnit, true, true);
+		ASTNode node = runConversion(getJLS8(), sourceUnit, true, true);
 		assertTrue("Not a compilation unit", node.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) node;
 		assertProblemsSize(unit, 0);
@@ -9744,7 +9744,7 @@
 		IField field = type.getField("i");
 		assertNotNull("No field", field);
 		ISourceRange sourceRange = field.getNameRange();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, sourceRange.getOffset() + sourceRange.getLength() / 2, false);
 		assertNotNull(result);
 	}
 	/**
@@ -9769,7 +9769,7 @@
 			newClasspathEntries.toArray(newClasspath);
 			project.setRawClasspath(newClasspath, null);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0689", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true, true);
 			assertNotNull(result);
 			ITypeBinding typeBinding = result.getAST().resolveWellKnownType("java.lang.Boolean");
 			assertNull("Should be null", typeBinding);
@@ -9799,7 +9799,7 @@
 			newClasspathEntries.toArray(newClasspath);
 			project.setRawClasspath(newClasspath, null);
 			ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0690", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-			ASTNode result = runConversion(AST.JLS8, sourceUnit, true, true, true);
+			ASTNode result = runConversion(getJLS8(), sourceUnit, true, true, true);
 			assertNotNull(result);
 			ITypeBinding typeBinding = result.getAST().resolveWellKnownType("java.lang.Boolean");
 			assertNull("Should be null", typeBinding);
@@ -9816,7 +9816,7 @@
 		IType type = unit.getType("X");
 		IMethod method = type.getMethod("foo", new String[0]);
 		
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setSource(unit);
 		Hashtable options = JavaCore.getOptions();
@@ -9861,7 +9861,7 @@
 		ICompilationUnit unit = getCompilationUnit("Converter" , "src", "test0693", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		ICompilationUnit unit2 = getCompilationUnit("Converter" , "src", "test0693", "Y.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ASTRequestor requestor = new ASTRequestor() {};
 		ICompilationUnit[] cus = new ICompilationUnit[2];
 		cus[0] = unit;
@@ -9882,7 +9882,7 @@
 		ICompilationUnit unit = getCompilationUnit("Converter" , "src", "test0694", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		ICompilationUnit unit2 = getCompilationUnit("Converter" , "src", "test0694", "Y.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ASTRequestor requestor = new ASTRequestor() {};
 		ICompilationUnit[] cus = new ICompilationUnit[2];
 		cus[0] = unit;
@@ -9902,7 +9902,7 @@
 	public void test0695() throws JavaModelException {
 		ICompilationUnit unit = getCompilationUnit("Converter" , "src", "test0695", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setSource(unit.getSource().toCharArray());
 		Map options = JavaCore.getOptions();
@@ -9927,7 +9927,7 @@
 	public void test0696() throws JavaModelException {
 		ICompilationUnit unit = getCompilationUnit("Converter" , "src", "test0696", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setSource(unit.getSource().toCharArray());
 		Map options = JavaCore.getOptions();
@@ -10045,7 +10045,7 @@
 			VariableDeclarationFragment fragment = (VariableDeclarationFragment) buildAST(contents, workingCopy, false, true, true);
 			IVariableBinding variableBinding = fragment.resolveBinding();
 			final String key = variableBinding.getKey();
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(workingCopy.getJavaProject());
 			parser.setResolveBindings(true);
 			parser.setKind(ASTParser.K_COMPILATION_UNIT);
@@ -10087,7 +10087,7 @@
 			VariableDeclarationFragment fragment = (VariableDeclarationFragment) buildAST(contents, workingCopy, false, true, true);
 			IVariableBinding variableBinding = fragment.resolveBinding();
 			final String key = variableBinding.getKey();
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(workingCopy.getJavaProject());
 			parser.setResolveBindings(true);
 			parser.setKind(ASTParser.K_COMPILATION_UNIT);
@@ -10130,7 +10130,7 @@
 			VariableDeclarationFragment fragment = (VariableDeclarationFragment) buildAST(contents, workingCopy, false, true, true);
 			IVariableBinding variableBinding = fragment.resolveBinding();
 			final String key = variableBinding.getKey();
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(workingCopy.getJavaProject());
 			parser.setResolveBindings(true);
 			parser.setKind(ASTParser.K_COMPILATION_UNIT);
@@ -10161,7 +10161,7 @@
 		final char[] source = ("void foo() {\n" + 
 				"	Integer I = new ${cursor}\n" +
 				"}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10185,7 +10185,7 @@
 				"		Integer I = new ${cursor}\n" + 
 				"	}\n" + 
 				"}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10207,7 +10207,7 @@
 		final char[] source = ("{\n" + 
 				"	Integer I = new ${cursor}\n" +
 				"}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10232,7 +10232,7 @@
 				"{\n" + 
 				"	Integer I = new ${cursor}\n" +
 				"}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10261,7 +10261,7 @@
 				"		Integer I = new ${cursor}\n" + 
 				"	};\"\n" + 
 				"}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_COMPILATION_UNIT);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10278,7 +10278,7 @@
 		final char[] source = ("Integer i = new Integer() {\n" + 
 				"	Integer I = new ${cursor}\n" + 
 				"};").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10292,7 +10292,7 @@
 	 */
 	public void test0708() throws JavaModelException {
 		final char[] source = ("System.out.println()\nint i;\n").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_STATEMENTS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10337,7 +10337,7 @@
 	 */
 	public void test0710() throws JavaModelException {
 		final char[] source = (";").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10352,7 +10352,7 @@
 	 */
 	public void test0711() throws JavaModelException {
 		final char[] source = (";void foo() {}").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10367,7 +10367,7 @@
 	 */
 	public void test0712() throws JavaModelException {
 		final char[] source = (";void foo() {};").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(true);
 		parser.setSource(source);
@@ -10390,7 +10390,7 @@
 				"      if (condition) appendAndExecute(new AddCommand(...));\n" + 
 				"    }\n" + 
 				"  }").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(false);
 		parser.setSource(source);
@@ -10439,7 +10439,7 @@
 				"      }\n" + 
 				"    }\n" + 
 				"  }").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(false);
 		parser.setSource(source);
@@ -10453,7 +10453,7 @@
 	 */
 	public void test0715() throws JavaModelException {
 		final char[] source = ("System.out.println()\nint i;\n").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_STATEMENTS);
 		parser.setStatementsRecovery(true);
 		parser.setIgnoreMethodBodies(true);
@@ -10470,7 +10470,7 @@
 	public void test0716() {
 		String src = "switch (state) {case 4:double M0,M1;}";
 		char[] source = src.toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		parser.setIgnoreMethodBodies(true);
 		parser.setSource (source);
@@ -10502,7 +10502,7 @@
 				"      if (condition) appendAndExecute(new AddCommand());\n" + 
 				"    }\n" + 
 				"  }").toCharArray();
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
 		parser.setStatementsRecovery(false);
 		parser.setIgnoreMethodBodies(true);
@@ -10615,7 +10615,7 @@
 	public void test0720() throws JavaModelException {
 		ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0720", "A.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 		char[] source = sourceUnit.getSource().toCharArray();
-		ASTNode result = runConversion(AST.JLS8, sourceUnit, true);
+		ASTNode result = runConversion(getJLS8(), sourceUnit, true);
 		assertTrue("not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT); //$NON-NLS-1$
 		CompilationUnit unit = (CompilationUnit) result;
 		assertEquals("Wrong number of problems", 1, unit.getProblems().length); //$NON-NLS-1$
@@ -10696,7 +10696,7 @@
 	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=347396
 	 */
 	public void test0723() {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_STATEMENTS);
 		String src = "int j;\nfor {};\nj=1000;";
 		char[] source = src.toCharArray();
@@ -10718,7 +10718,7 @@
 	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=347396
 	 */
 	public void test0724() {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setKind (ASTParser.K_COMPILATION_UNIT);
 		String src = "public class X { void foo() {int j;\nfor {};\nj=1000;}}";
 		char[] source = src.toCharArray();
@@ -10797,8 +10797,8 @@
 				"  public static final native long /*int*/ realpath(byte[] path, byte[] realPath);\n" +
 				"}"
 			);
-			// TODO improve test for AST.JLS8
-			CompilationUnit unit = sourceUnit.reconcile(AST.JLS8, false, null, null);
+			// TODO improve test for getJLS8()
+			CompilationUnit unit = sourceUnit.reconcile(getJLS8(), false, null, null);
 			assertEquals("Unexpected well known type", null, unit.getAST().resolveWellKnownType("void"));
 		} finally {
 			sourceUnit.discardWorkingCopy();
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 aa7c155..4450153 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, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -48,7 +48,7 @@
 				suite.addTest(new ASTMatcherTest(methods[i].getName(), AST.JLS2));
 				suite.addTest(new ASTMatcherTest(methods[i].getName(), JLS3_INTERNAL));
 				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898
-				suite.addTest(new ASTMatcherTest(methods[i].getName(), AST.JLS8));
+				suite.addTest(new ASTMatcherTest(methods[i].getName(), getJLS8()));
 			}
 		}
 		return suite;
@@ -119,6 +119,13 @@
 	}
 
 	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
+
+	/**
 	 * @deprecated (not really - just suppressing the warnings
 	 * that come from testing Javadoc.getComment())
 	 *
@@ -140,7 +147,7 @@
 		this.S1 = this.ast.newContinueStatement();
 		this.S2 = this.ast.newBreakStatement();
 		this.B1 = this.ast.newBlock();
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			this.R1 = this.ast.newSimpleType(this.ast.newSimpleName("XYZ"));
 			this.Q1 = this.ast.newSimpleName("XYZ");
 		}
@@ -242,7 +249,7 @@
 			this.EC2 = this.ast.newEnumConstantDeclaration();
 			this.EC2.setName(this.ast.newSimpleName("G")); //$NON-NLS-1$
 		}
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			this.T3 = this.ast.newSimpleType(this.ast.newSimpleName("U")); //$NON-NLS-1$
 			this.T4 = this.ast.newSimpleType(this.ast.newSimpleName("V")); //$NON-NLS-1$
 		}
@@ -721,7 +728,7 @@
 
 	/** @deprecated using deprecated code */
 	public void testNameQualifiedType() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		Type x1 = this.ast.newNameQualifiedType(this.ast.newQualifiedName(this.N2, this.N3), this.N1);
@@ -881,7 +888,7 @@
 	}
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794
 	public void testCreationReference() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		CreationReference x1 = this.ast.newCreationReference();
@@ -946,7 +953,7 @@
 	}
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794
 	public void testExpressionMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		ExpressionMethodReference x1 = this.ast.newExpressionMethodReference();
@@ -1063,14 +1070,14 @@
 			x1.typeParameters().add(this.TP1);
 			x1.typeParameters().add(this.TP2);
 			x1.setReturnType2(this.T1);
-			if (this.ast.apiLevel() >= AST.JLS8) {
+			if (this.ast.apiLevel() >= getJLS8()) {
 				x1.setReceiverType(this.R1);
 			}
 		}
 		x1.setName(this.N1);
 		x1.parameters().add(this.V1);
 		x1.parameters().add(this.V2);
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x1.thrownExceptions().add(this.N2);
 			x1.thrownExceptions().add(this.N3);			
 		} else {
@@ -1188,7 +1195,7 @@
 		basicMatch(x1);
 	}
 	public void testSuperMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		SuperMethodReference x1 = this.ast.newSuperMethodReference();
@@ -1416,7 +1423,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898
 	public void testSingleVariableDeclarationVarargsAnnotation() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		SingleVariableDeclaration x1 = this.ast.newSingleVariableDeclaration();
@@ -1429,7 +1436,7 @@
 	
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=395886
 	public void testQualifiedTypeAnnotation() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		QualifiedType x1 = this.ast.newQualifiedType(this.T1, this.N1);
@@ -1441,7 +1448,7 @@
 	
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=395886
 	public void testParameterizedQualifiedTypeAnnotation() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		QualifiedType qualifiedType = this.ast.newQualifiedType(this.T1, this.N1); 
@@ -1458,7 +1465,7 @@
 	
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations1() {	
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// simpleType with Annotations
@@ -1469,7 +1476,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations2() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
   		// Type arguments at parameterized types
@@ -1484,7 +1491,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations3() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// type arguments in constructor invocation
@@ -1497,7 +1504,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations4() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// annotated simple type at class inheritance
@@ -1511,7 +1518,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations5() {	
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// constructor invocation results
@@ -1524,7 +1531,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations6() {	
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// simple type in cast expression
@@ -1537,7 +1544,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations7() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// simple type type tests
@@ -1551,7 +1558,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations8() {	
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// annotations on wildcard type
@@ -1564,7 +1571,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations9() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// annotations on constructor declaration - implying on the object returned.
@@ -1577,7 +1584,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations10() {		
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// annotations on constructor declaration - implying on the object returned.
@@ -1592,7 +1599,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations11() {	
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		// annotated simple type at class inheritance
@@ -1607,7 +1614,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
 	public void testTypeAnnotations12() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		VariableDeclarationFragment x1 = this.ast.newVariableDeclarationFragment();
@@ -1630,7 +1637,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794
 	public void testTypeMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		TypeMethodReference x1 = this.ast.newTypeMethodReference();
@@ -1641,7 +1648,7 @@
 	
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793
 	public void testLambdaExpressions1() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		LambdaExpression x1 = this.ast.newLambdaExpression();
@@ -1654,7 +1661,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793
 	public void testLambdaExpressions2() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		LambdaExpression x1 = this.ast.newLambdaExpression();
@@ -1664,7 +1671,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793
 	public void testLambdaExpressions3() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		LambdaExpression x1 = this.ast.newLambdaExpression();
@@ -1674,7 +1681,7 @@
 
 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793
 	public void testLambdaExpressions4() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		LambdaExpression x1 = this.ast.newLambdaExpression();
@@ -1688,7 +1695,7 @@
 		basicMatch(x1);
 	}
 	public void testIntersectionType() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		IntersectionType x1 = this.ast.newIntersectionType();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
index 5f32640..eb0e1e6 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -79,6 +79,13 @@
 		);
 	}
 
+	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
+
 	/*
 	 * Removes the marker comments "*start*" and "*end*" from the given contents,
 	 * builds an AST from the resulting source, and returns the AST node that was delimited
@@ -532,7 +539,7 @@
 		this.workingCopies = new ICompilationUnit[2];
 		this.workingCopies[1] = getWorkingCopy("/P/src/Bar.java", barSource, this.wcOwner);
 		
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setProject(getJavaProject("P"));
 		parser.setSource(this.workingCopies[1]);
 		parser.setResolveBindings(true);
@@ -1309,7 +1316,7 @@
 				"}");
 		this.workingCopy.makeConsistent(null);
 		IMethod method = this.workingCopy.getType("X").getMethod("foo", new String[]{"QString;", "I"});
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setProject(getJavaProject("P"));
 		IBinding[] bindings = parser.createBindings(method.getParameters(), null);
 		assertBindingsEqual(
@@ -1328,7 +1335,7 @@
 				"  void foo(String str, int i) {}\n" +
 				"}");
 		IMethod method = getClassFile("/P/lib/A.class").getType().getMethod("foo", new String[] {"Ljava.lang.String;", "I"});
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setProject(getJavaProject("P"));
 		IBinding[] bindings = parser.createBindings(method.getParameters(), null);
 		assertBindingsEqual(
@@ -1360,7 +1367,7 @@
 		);
 
 		IJavaElement elem= this.workingCopies[0].codeSelect(xSource.indexOf("foo"), 0)[0];
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setProject(getJavaProject("P"));
 		IBinding[] bindings = parser.createBindings(new IJavaElement[]{ elem }, null);
 		assertBindingsEqual(
@@ -1392,7 +1399,7 @@
 			IType typeA = javaProject.findType("p.A");
 			
 			IJavaElement[] elems= typeA.getMethod("foo", new String[]{"I", "Z"}).getParameters();
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(javaProject);
 			IBinding[] bindings = parser.createBindings(elems, null);
 			assertBindingsEqual(
@@ -2622,7 +2629,7 @@
 					javaProject.findType("lib.A").getTypeParameters()[0],
 					javaProject.findType("lib.A").getTypeParameters()[1]
 				};
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(javaProject);
 			IBinding[] bindings = parser.createBindings(elements, null);
 			assertBindingsEqual(
@@ -2655,7 +2662,7 @@
 					method.getTypeParameters()[0],
 					method.getTypeParameters()[1]
 				};
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(getJLS8());
 			parser.setProject(javaProject);
 			IBinding[] bindings = parser.createBindings(elements, null);
 			assertBindingsEqual(
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodesCollectorVisitor.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodesCollectorVisitor.java
index ef3396c..4469cd2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodesCollectorVisitor.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTNodesCollectorVisitor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -145,6 +149,13 @@
 	}
 
 	/**
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.ModuleDeclaration)
+	 */
+	public void endVisit(ModuleDeclaration node) {
+		node.setName(node.getAST().newSimpleName("XXX")); //$NON-NLS-1$
+	}
+
+	/**
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.MethodInvocation)
 	 */
 	public void endVisit(MethodInvocation node) {
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 3909178..29fa62f 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -369,7 +373,7 @@
 				// oops - guess that's not valid
 			}
 		}
-		assertEquals("Wrong last known type", 92, hi); // last known one
+		assertEquals("Wrong last known type", 98, hi); // last known one
 		assertEquals("Wrong number of distinct types",  hi, classes.size()); // all classes are distinct
 	}
 }
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 7f0ef7a..25721a5 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -37,7 +41,12 @@
 	 * @deprecated
 	 */
 	/*package*/ static final int JLS3_INTERNAL = AST.JLS3;
-	
+	/**
+	 * Internal synonym for constant AST.JSL9
+	 * to alleviate deprecation warnings once AST.JLS9 is deprecated in future.
+	 */
+	protected static final int AST_INTERNAL_JLS9 = AST.JLS9;
+
 	class CheckPositionsMatcher extends ASTMatcher {
 
 		public CheckPositionsMatcher() {
@@ -748,7 +757,7 @@
 				suite.addTest(new ASTTest(methods[i].getName(), AST.JLS2));
 				suite.addTest(new ASTTest(methods[i].getName(), JLS3_INTERNAL));
 				suite.addTest(new ASTTest(methods[i].getName(), AST.JLS4));
-				suite.addTest(new ASTTest(methods[i].getName(), AST.JLS8));
+				suite.addTest(new ASTTest(methods[i].getName(), getJLS8()));
 			}
 		}
 		return suite;
@@ -757,6 +766,13 @@
 	AST ast;
 	int API_LEVEL;
 
+	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
+
 	public ASTTest(String name) {
 		super(name.substring(0, name.indexOf(" - JLS")));
 		name.indexOf(" - JLS");
@@ -2084,7 +2100,7 @@
 		previousCount = this.ast.modificationCount();
 		assertTrue(x.getAST() == this.ast);
 		assertTrue(x.getParent() == null);
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			assertTrue(getArrayComponentType(x).getParent() == x);
 		} else {
 			assertTrue(x.getElementType().getParent() == x);
@@ -2103,7 +2119,7 @@
 		assertTrue(x.getDimensions() == 1);
 		assertTrue(x.getElementType() == x2);
 
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			genericPropertyTest(x, new Property("ComponentType", true, Type.class) { //$NON-NLS-1$
 				public ASTNode sample(AST targetAst, boolean parented) {
 					SimpleType result = targetAst.newSimpleType(
@@ -3218,7 +3234,7 @@
 		}
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x.setExtraDimensions(1);
 		} else {
 			x.extraDimensions().add(this.ast.newDimension());
@@ -3227,7 +3243,7 @@
 		assertTrue(x.getExtraDimensions() == 1);
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x.setExtraDimensions(0);
 		} else {
 			x.extraDimensions().remove(0);
@@ -3330,7 +3346,7 @@
 			}
 		});
 
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			genericPropertyListTest(x, x.extraDimensions(),
 					new Property("ExtraDimensions", true, Dimension.class) { //$NON-NLS-1$
 						public ASTNode sample(AST targetAst, boolean parented) {
@@ -3388,7 +3404,7 @@
 		assertTrue(this.ast.modificationCount() == previousCount);
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			setExtraDimensions(x, 1);
 		} else {
 			x.extraDimensions().add(this.ast.newDimension());
@@ -3397,7 +3413,7 @@
 		assertTrue(x.getExtraDimensions() == 1);
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			setExtraDimensions(x, 0);
 		} else {
 			x.extraDimensions().remove(0);
@@ -3406,7 +3422,7 @@
 		assertTrue(x.getExtraDimensions() == 0);
 
 		// check that property cannot be set negative
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			try {
 				setExtraDimensions(x, -1);
 				fail();
@@ -3431,7 +3447,7 @@
 			}
 		});
 
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			genericPropertyListTest(x, x.extraDimensions(),
 					new Property("ExtraDimensions", true, Dimension.class) { //$NON-NLS-1$
 						public ASTNode sample(AST targetAst, boolean parented) {
@@ -3510,7 +3526,7 @@
 		assertTrue(x.getExtraDimensions() == 0);
 		assertTrue(x.getJavadoc() == null);
 		assertTrue(x.parameters().size() == 0);
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			assertTrue(x.thrownExceptions().size() == 0);			
 		} else {
 			assertTrue(x.thrownExceptionTypes().size() == 0);			
@@ -3550,7 +3566,7 @@
 		}
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x.setExtraDimensions(1);
 		} else {
 			x.extraDimensions().add(this.ast.newDimension());
@@ -3559,7 +3575,7 @@
 		assertTrue(x.getExtraDimensions() == 1);
 
 		previousCount = this.ast.modificationCount();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x.setExtraDimensions(0);
 		} else {
 			x.extraDimensions().remove(0);
@@ -3637,7 +3653,7 @@
 			});
 		}
 
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			genericPropertyListTest(x, x.extraDimensions(),
 					new Property("ExtraDimensions", true, Dimension.class) { //$NON-NLS-1$
 						public ASTNode sample(AST targetAst, boolean parented) {
@@ -3675,7 +3691,7 @@
 			}
 		});
 
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			genericPropertyListTest(x, x.thrownExceptions(),
 					  new Property("ThrownExceptions", true, Name.class) { //$NON-NLS-1$
 						public ASTNode sample(AST targetAst, boolean parented) {
@@ -3742,7 +3758,7 @@
 			x.parameters().add(this.ast.newSingleVariableDeclaration());
 			assertTrue(!x.isVarargs()); // only last param counts
 		}
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			try {
 				x.setExtraDimensions(-1);
 				fail("Should fail");
@@ -6470,6 +6486,10 @@
 				assertTrue(node.resolveBinding() == null);
 				return true;
 			}
+			public boolean visit(ModuleDeclaration node) {
+//				assertTrue(node.resolveBinding() == null);//TODO: enable after bug 515875 enables module binding
+				return true;
+			}
 			public boolean visit(TypeDeclaration node) {
 				assertTrue(node.resolveBinding() == null);
 				return true;
@@ -8840,14 +8860,20 @@
 			ASTNode.CREATION_REFERENCE,
 			ASTNode.EXPRESSION_METHOD_REFERENCE,
 			ASTNode.SUPER_METHOD_REFERENCE,
-			ASTNode.TYPE_METHOD_REFERENCE
+			ASTNode.TYPE_METHOD_REFERENCE,
+			ASTNode.MODULE_DECLARATION,
+			ASTNode.EXPORTS_STATEMENT,
+			ASTNode.REQUIRES_STATEMENT,
+			ASTNode.USES_STATEMENT,
+			ASTNode.PROVIDES_STATEMENT,
+			ASTNode.OPENS_STATEMENT
 		};
-		
+
 		// assert that nodeType values are correct:
 		for (int i= 0; i < nodeTypes.length; i++) {
 			assertSame(i + 1, nodeTypes[i]);
 		}
-		
+
 		// test nodeClassForType:
 		for (int i= 0; i < nodeTypes.length; i++) {
 			int nodeType = nodeTypes[i];
@@ -8855,7 +8881,7 @@
 			try {
 				node = this.ast.createInstance(nodeType);
 			} catch (IllegalArgumentException e) {
-				if (this.API_LEVEL < AST.JLS8 && e.getCause() instanceof UnsupportedOperationException) {
+				if (this.API_LEVEL < AST_INTERNAL_JLS9 && e.getCause() instanceof UnsupportedOperationException) {
 					continue;
 				} else {
 					throw new AssertionFailedError("missing node type: " + nodeType);
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 d47d83f..a708434 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -32,7 +36,7 @@
 				suite.addTest(new ASTVisitorTest(methods[i].getName(), AST.JLS2));
 				suite.addTest(new ASTVisitorTest(methods[i].getName(), AST.JLS3));
 				suite.addTest(new ASTVisitorTest(methods[i].getName(), AST.JLS4));
-				suite.addTest(new ASTVisitorTest(methods[i].getName(), AST.JLS8));
+				suite.addTest(new ASTVisitorTest(methods[i].getName(), getJLS8()));
 			}
 		}
 		return suite;
@@ -299,7 +303,7 @@
 			this.EC2.setName(this.ast.newSimpleName("d")); //$NON-NLS-1$
 			this.EC2S = "[(ECD[(nSddnS)]ECD)]"; //$NON-NLS-1$
 		}
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= getJLS8()) {
 			this.T3 = this.ast.newSimpleType(this.ast.newSimpleName("W")); //$NON-NLS-1$
 			this.T3S = "[(tS[(nSWWnS)]tS)]"; //$NON-NLS-1$
 			this.T4 = this.ast.newSimpleType(this.ast.newSimpleName("X")); //$NON-NLS-1$
@@ -312,6 +316,12 @@
 		this.ast = null;
 		super.tearDown();
 	}
+	/**
+	 * @deprecated
+	 */
+	protected static int getJLS8() {
+		return AST.JLS8;
+	}
 
 	class TestVisitor extends ASTVisitor {
 
@@ -801,6 +811,14 @@
 			ASTVisitorTest.this.b.append("eMI)"); //$NON-NLS-1$
 		}
 
+		public boolean visit(ModuleDeclaration node) {
+			ASTVisitorTest.this.b.append("(MoD"); //$NON-NLS-1$
+			return isVisitingChildren();
+		}
+		public void endVisit(ModuleDeclaration node) {
+			ASTVisitorTest.this.b.append("MoD)"); //$NON-NLS-1$
+		}
+
 		public boolean visit(NullLiteral node) {
 			ASTVisitorTest.this.b.append("(eNL"); //$NON-NLS-1$
 			return isVisitingChildren();
@@ -1154,13 +1172,13 @@
 		this.b.setLength(0);
 		x1.accept(v1);
 		String result = this.b.toString();
-		String expected = this.ast.apiLevel() < AST.JLS8 ? "[(tA[(tPcharchartP)]tA)]" : "[(tA[(tPcharchartP)][(@ED@ED)]tA)]";
+		String expected = this.ast.apiLevel() < getJLS8() ? "[(tA[(tPcharchartP)]tA)]" : "[(tA[(tPcharchartP)][(@ED@ED)]tA)]";
 		assertTrue(expected.equals(result)); //$NON-NLS-1$
 	}
 
 	/** @deprecated using deprecated code */
 	public void testNameQualifiedType() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		QualifiedName q = this.ast.newQualifiedName(this.N2, this.N3);
@@ -1252,7 +1270,7 @@
 		this.b.setLength(0);
 		x1.accept(v1);
 		String result = this.b.toString();
-		String dim = this.ast.apiLevel() < AST.JLS8 ? "" : "[(@ED@ED)]";
+		String dim = this.ast.apiLevel() < getJLS8() ? "" : "[(@ED@ED)]";
 		assertTrue(result.equals("[(eAC"+"[(tA"+this.T1S+ dim +"tA)]"+this.E1S+this.E2S+"[(eAIeAI)]eAC)]")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
 	}
 	public void testArrayInitializer() {
@@ -1449,7 +1467,7 @@
 	}
 
 	public void testCreationReference() {
-		if (this.ast.apiLevel() < AST.JLS8)
+		if (this.ast.apiLevel() < getJLS8())
 			return;
 		CreationReference x1 = this.ast.newCreationReference();
 		x1.setType(this.T1);
@@ -1521,7 +1539,7 @@
 		assertTrue(result.equals("[(ED"+this.JD1S+this.MOD1S+this.MOD2S+this.N1S+this.T1S+this.T2S+this.EC1S+this.EC2S+this.FD1S+this.FD2S+"ED)]")); //$NON-NLS-1$ //$NON-NLS-2$
 	}
 	public void testExpressionMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8)
+		if (this.ast.apiLevel() < getJLS8())
 			return;
 		ExpressionMethodReference x1 = this.ast.newExpressionMethodReference();
 		x1.setExpression(this.E1);
@@ -1542,7 +1560,7 @@
 		assertTrue(result.equals("[(sEX"+this.E1S+"sEX)]")); //$NON-NLS-1$ //$NON-NLS-2$
 	}
 	public void testExtraDimension() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		Dimension x1 = this.ast.newDimension();
@@ -1760,7 +1778,7 @@
 		x1.setName(this.N1);
 		x1.parameters().add(this.V1);
 		x1.parameters().add(this.V2);
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			x1.thrownExceptions().add(this.N2);
 			x1.thrownExceptions().add(this.N3);			
 		} else {
@@ -1774,7 +1792,7 @@
 		String result = this.b.toString();
 		if (this.ast.apiLevel() == AST.JLS2) {
 			assertEquals("[(MD"+this.JD1S+this.T1S+this.N1S+this.V1S+this.V2S+this.N2S+this.N3S+this.B1S+"MD)]", result); //$NON-NLS-1$ //$NON-NLS-2$
-		} else if (this.ast.apiLevel() < AST.JLS8) {
+		} else if (this.ast.apiLevel() < getJLS8()) {
 			assertEquals("[(MD"+this.JD1S+this.MOD1S+this.MOD2S+this.TP1S+this.T1S+this.N1S+this.V1S+this.V2S+this.N2S+this.N3S+this.B1S+"MD)]", result); //$NON-NLS-1$ //$NON-NLS-2$
 		} else {
 			assertEquals("[(MD"+this.JD1S+this.MOD1S+this.MOD2S+this.TP1S+this.T1S+this.N1S+this.V1S+this.V2S+this.T3S+this.T4S+this.B1S+"MD)]", result); //$NON-NLS-1$ //$NON-NLS-2$			
@@ -2067,7 +2085,7 @@
 		}
 	}
 	public void testSuperMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < getJLS8()) {
 			return;
 		}
 		SuperMethodReference x1 = this.ast.newSuperMethodReference();
@@ -2226,7 +2244,7 @@
 		assertTrue(result.equals("[(eTL"+this.T1S+"eTL)]")); //$NON-NLS-1$ //$NON-NLS-2$
 	}
 	public void testTypeMethodReference() {
-		if (this.ast.apiLevel() < AST.JLS8)
+		if (this.ast.apiLevel() < getJLS8())
 			return;
 		TypeMethodReference x1 = this.ast.newTypeMethodReference();
 		x1.setType(this.T1);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
index 310a106..2ffcae1 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -75,6 +79,12 @@
 	 * @deprecated
 	 */
 	/*package*/ static final int AST_INTERNAL_JLS4 = AST.JLS4;
+	/**
+	 * Internal synonym for deprecated constant AST.JSL8
+	 * to alleviate deprecation warnings.
+	 * @deprecated
+	 */
+	/*package*/ static final int AST_INTERNAL_JLS8 = AST.JLS8;
 	public static final int astInternalJLS2() {
 		return AST_INTERNAL_JLS2;
 	}
@@ -483,8 +493,10 @@
 		String option = cu.getJavaProject().getOption(JavaCore.COMPILER_COMPLIANCE, true);
 		long jdkLevel = CompilerOptions.versionToJdkLevel(option);
 		int JLSLevel = AST_INTERNAL_JLS3;
-		if (jdkLevel >= ClassFileConstants.JDK1_8) {
-			JLSLevel = AST.JLS8;
+		if (jdkLevel >= ClassFileConstants.JDK9) {
+			JLSLevel = AST_INTERNAL_JLS9;			
+		} else if (jdkLevel >= ClassFileConstants.JDK1_8) {
+			JLSLevel = AST_INTERNAL_JLS8;
 		} else if (jdkLevel >= ClassFileConstants.JDK1_7) {
 			JLSLevel = AST_INTERNAL_JLS4;
 		}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BindingsCollectorVisitor.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BindingsCollectorVisitor.java
index b762e5e..f3c2c18 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BindingsCollectorVisitor.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/BindingsCollectorVisitor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -227,6 +231,14 @@
 	}
 
 	/**
+	 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(ModuleDeclaration)
+	 */
+	public void endVisit(ModuleDeclaration node) {
+/*		IModuleBinding moduleBinding = node.resolveBinding();//TODO: enable after bug 515875 enables module binding
+		collectBindings(node, moduleBinding);*/
+	}
+
+	/**
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(MethodInvocation)
 	 */
 	public void endVisit(MethodInvocation node) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ConverterTestSetup.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ConverterTestSetup.java
index 9d6f3ce..c9440fe 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ConverterTestSetup.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ConverterTestSetup.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -42,6 +46,13 @@
 	 */
 	/*package*/ static final int JLS4_INTERNAL = AST.JLS4;
 
+	/**
+	 * Internal synonym for deprecated constant AST.JSL8
+	 * to alleviate deprecation warnings.
+	 * @deprecated
+	 */
+	/*package*/ static final int JLS8_INTERNAL = AST.JLS8;
+
 	static int getJLS3() {
 		return JLS3_INTERNAL;
 	}
@@ -49,7 +60,10 @@
 	static int getJLS4() {
 		return JLS4_INTERNAL;
 	}
-	
+
+	static int getJLS8() {
+		return JLS8_INTERNAL;
+	}	
 	protected AST ast;
 	public static List TEST_SUITES = null;
 	public static boolean PROJECT_SETUP = false;
@@ -89,6 +103,7 @@
 			this.deleteProject("Converter16"); //$NON-NLS-1$
 			this.deleteProject("Converter17"); //$NON-NLS-1$
 			this.deleteProject("Converter18"); //$NON-NLS-1$
+			this.deleteProject("Converter9"); //$NON-NLS-1$
 			PROJECT_SETUP = false;
 		} else {
 			TEST_SUITES.remove(getClass());
@@ -98,6 +113,7 @@
 				this.deleteProject("Converter16"); //$NON-NLS-1$
 				this.deleteProject("Converter17"); //$NON-NLS-1$
 				this.deleteProject("Converter18"); //$NON-NLS-1$
+				this.deleteProject("Converter9"); //$NON-NLS-1$
 				PROJECT_SETUP = false;
 			}
 		}
@@ -106,6 +122,10 @@
 	}
 
 	public void setUpJCLClasspathVariables(String compliance, boolean useFullJCL) throws JavaModelException, IOException {
+		if (useFullJCL) {
+			 super.setUpJCLClasspathVariables(compliance, useFullJCL);
+			 return;
+		}
 		if ("1.5".equals(compliance)
 				|| "1.6".equals(compliance)) {
 			if (JavaCore.getClasspathVariable("CONVERTER_JCL15_LIB") == null) {
@@ -123,7 +143,7 @@
 					new IPath[] {getConverterJCLPath("1.7"), getConverterJCLSourcePath("1.7"), getConverterJCLRootSourcePath()},
 					null);
 			}
-		} else if ("1.8".equals(compliance)) {
+		} else if ("1.8".equals(compliance) || "9".equals(compliance)) {
 			if (JavaCore.getClasspathVariable("CONVERTER_JCL18_LIB") == null) {
 				setupExternalJCL("converterJclMin1.8");
 				JavaCore.setClasspathVariables(
@@ -152,6 +172,7 @@
 			setUpJavaProject("Converter16", "1.6"); //$NON-NLS-1$ //$NON-NLS-2$
 			setUpJavaProject("Converter17", "1.7"); //$NON-NLS-1$ //$NON-NLS-2$
 			setUpJavaProject("Converter18", "1.8"); //$NON-NLS-1$ //$NON-NLS-2$
+			setUpJavaProject("Converter9", "9"); //$NON-NLS-1$ //$NON-NLS-2$
 			waitUntilIndexesReady(); // needed to find secondary types
 			PROJECT_SETUP = true;
 		}
@@ -407,6 +428,10 @@
 			super.endVisit(node);
 		}
 
+		public void endVisit(ModuleDeclaration node) {
+//			assertNotNull(node+" should have a binding", node.resolveBinding());//TODO: enable after bug 515875 enables module binding
+			super.endVisit(node);
+		}
 		public void endVisit(MethodRef node) {
 			assertNotNull(node+" should have a binding", node.resolveBinding());
 			super.endVisit(node);
@@ -548,6 +573,9 @@
 		return runJLS8Conversion(unit, resolveBindings, checkJLS2, false);
 	}
 
+	/**
+	 * @deprecated references deprecated old AST level
+	 */
 	public ASTNode runJLS8Conversion(ICompilationUnit unit, boolean resolveBindings, boolean checkJLS2, boolean bindingRecovery) {
 
 		// Create parser
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/MarkedASTFlattener.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/MarkedASTFlattener.java
index 94ea5ea..838b6dd 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/MarkedASTFlattener.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/MarkedASTFlattener.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2016 IBM Corporation and others.
+ * Copyright (c) 2008, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -249,6 +253,8 @@
 					buffer.append("ENUM_DECLARATION");break;
 				case ASTNode.EXPRESSION_STATEMENT :
 					buffer.append("EXPRESSION_STATEMENT");break;
+				case ASTNode.EXPORTS_STATEMENT :
+					buffer.append("EXPORTS_STATEMENT");break;
 				case ASTNode.FIELD_ACCESS :
 					buffer.append("FIELD_ACCESS");break;
 				case ASTNode.FIELD_DECLARATION :
@@ -287,12 +293,16 @@
 					buffer.append("METHOD_REF_PARAMETER");break;
 				case ASTNode.MODIFIER :
 					buffer.append("MODIFIER");break;
+				case ASTNode.MODULE_DECLARATION :
+					buffer.append("MODULE_DECLARATION");break;
 				case ASTNode.NORMAL_ANNOTATION :
 					buffer.append("NORMAL_ANNOTATION");break;
 				case ASTNode.NULL_LITERAL :
 					buffer.append("NULL_LITERAL");break;
 				case ASTNode.NUMBER_LITERAL :
 					buffer.append("NUMBER_LITERAL");break;
+				case ASTNode.OPENS_STATEMENT :
+					buffer.append("OPENS_STATEMENT");break;
 				case ASTNode.PACKAGE_DECLARATION :
 					buffer.append("PACKAGE_DECLARATION");break;
 				case ASTNode.PARAMETERIZED_TYPE :
@@ -305,10 +315,14 @@
 					buffer.append("PREFIX_EXPRESSION");break;
 				case ASTNode.PRIMITIVE_TYPE :
 					buffer.append("PRIMITIVE_TYPE");break;
+				case ASTNode.PROVIDES_STATEMENT :
+					buffer.append("PROVIDES_STATEMENT");break;
 				case ASTNode.QUALIFIED_NAME :
 					buffer.append("QUALIFIED_NAME");break;
 				case ASTNode.QUALIFIED_TYPE :
 					buffer.append("QUALIFIED_TYPE");break;
+				case ASTNode.REQUIRES_STATEMENT :
+					buffer.append("REQUIRES_STATEMENT");break;
 				case ASTNode.RETURN_STATEMENT :
 					buffer.append("RETURN_STATEMENT");break;
 				case ASTNode.SIMPLE_NAME :
@@ -351,6 +365,8 @@
 					buffer.append("TYPE_LITERAL");break;
 				case ASTNode.TYPE_PARAMETER :
 					buffer.append("TYPE_PARAMETER");break;
+				case ASTNode.USES_STATEMENT :
+					buffer.append("USES_STATEMENT");break;
 				case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
 					buffer.append("VARIABLE_DECLARATION_EXPRESSION");break;
 				case ASTNode.VARIABLE_DECLARATION_FRAGMENT :
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
index baca6e3..487e748 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -48,6 +52,7 @@
 		ASTConverter15JLS8Test.class,
 		TypeAnnotationsConverterTest.class,
 		ASTConverter18Test.class,
+		ASTConverter9Test.class,
 	};
 }
 public static Test suite() {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/SampleASTs.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/SampleASTs.java
index 59aeff5..c220883 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/SampleASTs.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/SampleASTs.java
@@ -29,7 +29,13 @@
 	 * @deprecated
 	 */
 	/*package*/ static final int JLS4_INTERNAL = AST.JLS4;
-	
+
+	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
 	/**
 	 * Returns a subtree of sample of AST nodes. The sample includes
 	 * one of each kind (except for BlockComment and LineComment,
@@ -93,7 +99,7 @@
 			pmt.typeArguments().add(qt);
 			md.setReturnType2(pmt);
 		}
-		if (target.apiLevel() >= AST.JLS8) {
+		if (target.apiLevel() >= getJLS8()) {
 			Dimension ed = target.newDimension();
 			md.extraDimensions().add(ed);
 		}
@@ -180,7 +186,7 @@
 		z.add(booleanLiteral);
 		CastExpression castExpression = target.newCastExpression();
 		z.add(castExpression);
-		if (target.apiLevel() >= AST.JLS8) {
+		if (target.apiLevel() >= getJLS8()) {
 			IntersectionType it = target.newIntersectionType();
 			castExpression.setType(it);
 		}
@@ -198,7 +204,7 @@
 		z.add(infixExpression);
 		InstanceofExpression instanceofExpression = target.newInstanceofExpression();
 		z.add(instanceofExpression);
-		if (target.apiLevel() >= AST.JLS8) {
+		if (target.apiLevel() >= getJLS8()) {
 			LambdaExpression lambdaExpression = target.newLambdaExpression();
 			z.add(lambdaExpression);
 		}
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 ce4e062..557217c 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -23,7 +27,7 @@
 
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(AST_INTERNAL_JLS9);
 	}
 
 	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 40cdcd1..ed4309a 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -78,7 +78,13 @@
 	}
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
-		this.ast = AST.newAST(AST.JLS8);
+		this.ast = AST.newAST(getAST8());
+	}
+	/**
+	 * @deprecated
+	 */
+	protected int getAST8() {
+		return AST.JLS8;
 	}
 	public TypeBindingTests308(String testName){
 		super(testName);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index 3eda4a0..67a7006 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -14005,4 +14005,42 @@
 	String input = getCompilationUnit("Formatter", "", "test362260", "G_in.java").getSource();
 	formatSource(input, getCompilationUnit("Formatter", "", "test362260", "G_out.java").getSource());
 }
+/**
+ * https://bugs.eclipse.org/506430 - [1.9] Formatter support for module-info.java
+ */
+public void testBug506430a() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_9);
+	setPageWidth80();
+	String input = getCompilationUnit("Formatter", "", "test506430", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test506430", "A_out.java") .getSource(),
+			CodeFormatter.K_MODULE_INFO | CodeFormatter.F_INCLUDE_COMMENTS);
+}
+/**
+ * https://bugs.eclipse.org/506430 - [1.9] Formatter support for module-info.java
+ */
+public void testBug506430b() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_9);
+	setPageWidth80();
+	this.formatterPrefs.brace_position_for_type_declaration = DefaultCodeFormatterConstants.NEXT_LINE;
+	this.formatterPrefs.blank_lines_before_new_chunk = 2;
+	this.formatterPrefs.blank_lines_before_first_class_body_declaration = 3;
+	this.formatterPrefs.blank_lines_before_field = 1;
+	this.formatterPrefs.indent_body_declarations_compare_to_type_header = false;
+	this.formatterPrefs.insert_space_before_comma_in_multiple_field_declarations = true;
+	this.formatterPrefs.alignment_for_module_statements = Alignment.M_NEXT_PER_LINE_SPLIT;
+	this.formatterPrefs.insert_new_line_at_end_of_file_if_missing = true;
+	String input = getCompilationUnit("Formatter", "", "test506430", "B_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test506430", "B_out.java") .getSource(),
+			CodeFormatter.K_MODULE_INFO | CodeFormatter.F_INCLUDE_COMMENTS);
+}
+/**
+ * https://bugs.eclipse.org/506430 - [1.9] Formatter support for module-info.java
+ */
+public void testBug506430c() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_9);
+	setPageWidth80();
+	String input = getCompilationUnit("Formatter", "", "test506430", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test506430", "A_out.java") .getSource(),
+			CodeFormatter.K_UNKNOWN | CodeFormatter.F_INCLUDE_COMMENTS);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index 9e492c7..5ef43d29 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -24,6 +28,7 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.search.*;
@@ -68,6 +73,12 @@
 	protected boolean displayName = false;
 	protected String endChar = ",";
 
+	/**
+	 * Internal synonym for constant AST.JSL9
+	 * to alleviate deprecation warnings once AST.JLS9 is deprecated in future.
+	 */
+	protected static final int AST_INTERNAL_JLS9 = AST.JLS9;
+
 	public static class BasicProblemRequestor implements IProblemRequestor {
 		public void acceptProblem(IProblem problem) {}
 		public void beginReporting() {}
@@ -1270,7 +1281,7 @@
 	protected void createJar(String[] javaPathsAndContents, String jarPath, Map options) throws IOException {
 		org.eclipse.jdt.core.tests.util.Util.createJar(javaPathsAndContents, null, jarPath, null, "1.4", options);
 	}
-	
+
 	protected void createJar(String[] javaPathsAndContents, String jarPath, String[] classpath, String compliance) throws IOException {
 		org.eclipse.jdt.core.tests.util.Util.createJar(javaPathsAndContents, null,jarPath, classpath, compliance);
 	}
@@ -1278,7 +1289,22 @@
 	protected void createJar(String[] javaPathsAndContents, String jarPath, String[] classpath, String compliance, Map options) throws IOException {
 		org.eclipse.jdt.core.tests.util.Util.createJar(javaPathsAndContents, null, jarPath, classpath, compliance, options);
 	}
-	
+
+	protected IJavaProject createJava9Project(String name) throws CoreException {
+		return createJava9Project(name, new String[]{"src"});
+	}
+	protected IJavaProject createJava9Project(String name, String[] srcFolders) throws CoreException {
+		String bootModPath = System.getProperty("java.home") + File.separator +"/lib/jrt-fs.jar";
+		IClasspathEntry jrtEntry = JavaCore.newLibraryEntry(new Path(bootModPath), null, null, null, null, false);
+		IJavaProject project = this.createJavaProject(name, srcFolders, new String[0],
+				new String[0], "bin", "9");
+		IClasspathEntry[] old = project.getRawClasspath();
+		IClasspathEntry[] newPath = new IClasspathEntry[old.length +1];
+		System.arraycopy(old, 0, newPath, 0, old.length);
+		newPath[old.length] = jrtEntry;
+		project.setRawClasspath(newPath, null);
+		return project;
+	}
 	/*
 	}
 	 * Creates a Java project where prj=src=bin and with JCL_LIB on its classpath.
@@ -1796,8 +1822,13 @@
 					options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
 					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
 					javaProject.setOptions(options);
+				} else if ("9".equals(compliance)) {
+					Map options = new HashMap();
+					options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
+					options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
+					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
+					javaProject.setOptions(options);
 				}
-
 				result[0] = javaProject;
 			}
 		};
@@ -2759,6 +2790,41 @@
 			assertTrue("failed to set classpath", false);
 		}
 	}
+	protected IJavaProject setupModuleProject(String name, String[] sources) throws CoreException {
+		return setupModuleProject(name, sources, false);
+	}
+	protected IJavaProject setupModuleProject(String name, String[] sources, boolean addModulePathContainer) throws CoreException {
+		IClasspathEntry[] deps = null;
+		if (addModulePathContainer) {
+			IClasspathEntry containerEntry = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			deps = new IClasspathEntry[] {containerEntry};
+		}
+		return setupModuleProject(name, sources, deps);
+	}
+	protected IJavaProject setupModuleProject(String name, String[] sources, IClasspathEntry[] deps) throws CoreException {
+		return setupModuleProject(name, new String[]{"src"}, sources, deps);
+	}
+	protected IJavaProject setupModuleProject(String name, String[] srcFolders, String[] sources, IClasspathEntry[] deps) throws CoreException {
+		IJavaProject project = createJava9Project(name, srcFolders);
+		IProgressMonitor monitor = new NullProgressMonitor();
+		for (int i = 0; i < sources.length; i+= 2) {
+			IPath path = new Path(sources[i]);
+			IPath parentPath = path.removeLastSegments(1);
+			IFolder folder = project.getProject().getFolder(parentPath);
+			if (!folder.exists())
+				this.createFolder(folder.getFullPath());
+			IFile file = project.getProject().getFile(new Path(sources[i]));
+			file.create(new ByteArrayInputStream(sources[i+1].getBytes()), true, monitor);
+		}
+		if (deps != null) {
+			IClasspathEntry[] old = project.getRawClasspath();
+			IClasspathEntry[] newPath = new IClasspathEntry[old.length + deps.length];
+			System.arraycopy(old, 0, newPath, 0, old.length);
+			System.arraycopy(deps, 0, newPath, old.length, deps.length);
+			project.setRawClasspath(newPath, null);
+		}
+		return project;
+	}
 	/**
 	 * Check locally for the required JCL files, <jclName>.jar and <jclName>src.zip.
 	 * If not available, copy from the project resources.
@@ -2849,7 +2915,10 @@
 			newJclLibString = "JCL18_FULL";
 			newJclSrcString = "JCL18_SRC"; // Use the same source
 		} else {
-			if (compliance.charAt(2) > '7') {
+			if (compliance.length() < 3) {
+					newJclLibString = "JCL19_LIB";
+					newJclSrcString = "JCL19_SRC";
+			} else if (compliance.charAt(2) > '7') {
 				newJclLibString = "JCL18_LIB";
 				newJclSrcString = "JCL18_SRC";
 			} else if (compliance.charAt(2) > '4') {
@@ -2894,9 +2963,10 @@
 		IPath jclLib = new Path("JCL_LIB");
 		IPath jcl5Lib = new Path("JCL15_LIB");
 		IPath jcl8Lib = new Path("JCL18_LIB");
+		IPath jcl9Lib = new Path("JCL19_LIB");
 		IPath jclFull = new Path("JCL18_FULL");
 
-		return path.equals(jclLib) || path.equals(jcl5Lib) || path.equals(jcl8Lib) || path.equals(jclFull);
+		return path.equals(jclLib) || path.equals(jcl5Lib) || path.equals(jcl8Lib) || path.equals(jcl9Lib) || path.equals(jclFull);
 	}
 	public void setUpJCLClasspathVariables(String compliance) throws JavaModelException, IOException {
 		setUpJCLClasspathVariables(compliance, false);
@@ -2935,6 +3005,14 @@
 							new IPath[] {getExternalJCLPath("1.8"), getExternalJCLSourcePath("1.8"), getExternalJCLRootSourcePath()},
 							null);
 			}
+		} else if ("9".equals(compliance)) {
+			if (JavaCore.getClasspathVariable("JCL19_LIB") == null) {
+				setupExternalJCL("jclMin9");
+				JavaCore.setClasspathVariables(
+					new String[] {"JCL19_LIB", "JCL19_SRC", "JCL_SRCROOT"},
+					new IPath[] {getExternalJCLPath("9"), getExternalJCLSourcePath("9"), getExternalJCLRootSourcePath()},
+					null);
+			}
 		} else {
 			if (JavaCore.getClasspathVariable("JCL_LIB") == null) {
 				setupExternalJCL("jclMin");
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
index 387a787..9d43695 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaSearchTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -316,7 +320,12 @@
 					this.line.append("]");
 				}
 				ICompilationUnit unit = null;
-				if (element instanceof IMethod) {
+				if (element instanceof IModuleDescription) {
+					IModuleDescription md = (IModuleDescription) element;
+					this.line.append(" ");
+					append(md);
+					unit = md.getCompilationUnit();
+				} else if (element instanceof IMethod) {
 					this.line.append(" ");
 					IMethod method = (IMethod)element;
 					append(method);
@@ -596,6 +605,9 @@
 			}
 			this.line.append(")");
 		}
+		private void append(IModuleDescription md) {
+			this.line.append(md.getElementName());
+		}
 		private void append(IPackageFragment pkg) {
 			this.line.append(pkg.getElementName());
 		}
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 24aaeee..59f6a8b 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -45,6 +49,8 @@
 
 		// Project & Root API unit tests
 		JavaProjectTests.class,
+		// Modularity tests (Java 9)
+		ModuleBuilderTests.class,
 
 		// Compilation unit tests
 		CompilationUnitTests.class,
@@ -205,6 +211,8 @@
 
 		// Java model changes related to Java 8
 		JavaElement8Tests.class,
+
+		Java9ElementTests.class,
 	};
 
 	Class[] deprecatedClasses = getDeprecatedJDOMTestClasses();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
index 3c431dd..15454c7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompilationUnitTests.java
@@ -2596,7 +2596,7 @@
 				"public class X {}\n");
 		ICompilationUnit cuD = getCompilationUnit("/P/src/X.java");
 		
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 		parser.setProject(this.testProject);
 		parser.setSource(cuD);
 		parser.setResolveBindings(true);
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
new file mode 100644
index 0000000..02850ca
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
@@ -0,0 +1,597 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import java.util.Hashtable;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+
+import junit.framework.Test;
+
+public class CompletionTests9 extends AbstractJavaModelCompletionTests {
+
+	static {
+//		TESTS_NUMBERS = new int[] { 19 };
+//		TESTS_NAMES = new String[] {"test486988_001"};
+//		TESTS_NAMES = new String[] {"test0001"};
+}
+
+public CompletionTests9(String name) {
+	super(name);
+}
+
+public void setUpSuite() throws Exception {
+	if (COMPLETION_PROJECT == null)  {
+		COMPLETION_PROJECT = setUpJavaProject("Completion", "9", true);
+	} else {
+		setUpProjectCompliance(COMPLETION_PROJECT, "9", true);
+	}
+	super.setUpSuite();
+}
+
+public static Test suite() {
+	// TODO: change to compliance 9 once tests run with 9
+	return buildModelTestSuite(AbstractCompilerTest.F_1_8, CompletionTests9.class);
+}
+
+
+private void createTypePlus(String folder, String pack, String typeName, String plus, boolean isClass, boolean createFolder) throws CoreException {
+	String filePath;
+	String fileContent;
+	fileContent = "package " + pack + ";\n" + "public " + (isClass ? "class " : "interface ");
+	if (plus != null) fileContent = fileContent + plus;
+	fileContent = fileContent + typeName + " {}\n";
+	if (createFolder)  createFolder(folder + pack);
+	filePath = folder + pack + "/" + typeName + ".java";
+	createFile(filePath, fileContent);
+}
+
+private void createType(String folder, String pack, String typeName) throws CoreException {
+	createTypePlus(folder, pack, typeName, null, true /* isClass */, true /*createFolder */);
+}
+
+public void test486988_0001() throws Exception {
+	IJavaProject project = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project.open(null);
+		String projName = "/" + project.getElementName();
+		String packageName = "/src/";
+		String fullFilePath = projName + packageName + "module-info.java";
+		String fileContent =  "module my.mod { }\n";
+		createFile(fullFilePath, fileContent);
+		String completeBehind = "{";
+		int cursorLocation = fileContent.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(fullFilePath);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "exports[KEYWORD]{exports, null, null, exports, 49}\n"
+				+ "opens[KEYWORD]{opens, null, null, opens, 49}\n"
+				+ "provides[KEYWORD]{provides, null, null, provides, 49}\n"
+				+ "requires[KEYWORD]{requires, null, null, requires, 49}\n"
+				+ "uses[KEYWORD]{uses, null, null, uses, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		assertNotNull("Project Null", project);
+		deleteProject(project);
+	}
+}
+
+public void test486988_0002() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	String fileContent =  "module my.mod { }\n";
+
+	this.workingCopies[0] = getWorkingCopy("/Completion/src/module-info.java", fileContent);
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "{";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	String expected = "exports[KEYWORD]{exports, null, null, exports, null, 49}\n"
+			+ "opens[KEYWORD]{opens, null, null, opens, null, 49}\n"
+			+ "provides[KEYWORD]{provides, null, null, provides, null, 49}\n"
+			+ "requires[KEYWORD]{requires, null, null, requires, null, 49}\n"
+			+ "uses[KEYWORD]{uses, null, null, uses, null, 49}";
+	assertResults(expected,	requestor.getResults());
+}
+
+public void test486988_0003() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	String fileContent =  "module my.mod {e }\n";
+
+	this.workingCopies[0] = getWorkingCopy("/Completion/src/module-info.java", fileContent);
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "{e";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	String expected = "exports[KEYWORD]{exports, null, null, exports, null, 49}";
+	assertResults(expected,	requestor.getResults());
+}
+
+public void test486988_0004() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	String fileContent =  "module my.mod { p }\n";
+
+
+	this.workingCopies[0] = getWorkingCopy("/Completion/src/module-info.java", fileContent);
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "p";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	Hashtable<String, String> tmpOld = JavaCore.getOptions();
+	Hashtable<String, String> options = new Hashtable<>(tmpOld);
+	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
+	JavaCore.setOptions(options);
+
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+
+	JavaCore.setOptions(tmpOld);
+	String expected = "provides[KEYWORD]{provides, null, null, provides, null, 49}";
+	assertResults(expected,	requestor.getResults());
+}
+
+// run locally until th
+public void _test486988_0005() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	String fileContent =  "module my.mod { p }\n";
+
+	this.workingCopies[0] = getWorkingCopy("/Completion/src/module-info.java", fileContent);
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "p";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	Hashtable<String, String> tmpOld = JavaCore.getOptions();
+	Hashtable<String, String> options = new Hashtable<>(tmpOld);
+	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
+	JavaCore.setOptions(options);
+
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+
+	JavaCore.setOptions(tmpOld);
+	String expected = "exports[KEYWORD]{exports, null, null, exports, null, 19}\n"
+			+ "provides[KEYWORD]{provides, null, null, provides, null, 49}";
+	assertResults(expected,	requestor.getResults());
+}
+
+public void _test486988_0006() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	String fileContent =  "module my.mod { u }\n";
+
+	this.workingCopies[0] = getWorkingCopy("/Completion/src/module-info.java", fileContent);
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "u";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+
+	Hashtable<String, String> tmpOld = JavaCore.getOptions();
+	Hashtable<String, String> options = new Hashtable<>(tmpOld);
+	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
+	JavaCore.setOptions(options);
+
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+
+	JavaCore.setOptions(tmpOld);
+
+	String expected = "requires[KEYWORD]{requires, null, null, requires, null, 19}\n"
+			+ "uses[KEYWORD]{uses, null, null, uses, null, 49}";
+	assertResults(expected, requestor.getResults());
+}
+
+public void test486988_0007() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[4];
+	String fileContent =  "module my.mod {"
+			+ "exports mypa"
+			+ "}\n";
+
+	this.workingCopies[0] = getWorkingCopy(
+			"/Completion/src/module-info.java", fileContent);
+	
+	this.workingCopies[1] = getWorkingCopy(
+			"/Completion/src/mypack1/Y.java",
+			"package pack1;\n" +
+			"public class Y {\n" +
+			"}");
+
+	this.workingCopies[2] = getWorkingCopy(
+			"/Completion/src/mypack2/Z.java",
+			"package pack2;\n" +
+			"public class Z {\n" +
+			"}");
+
+	this.workingCopies[3] = getWorkingCopy(
+			"/Completion/src/mypack1.mypack2/Z.java",
+			"package mypack1.mypack2;\n" +
+			"public class Z {\n" +
+			"}");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "mypa";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+
+	Hashtable<String, String> tmpOld = JavaCore.getOptions();
+	Hashtable<String, String> options = new Hashtable<>(tmpOld);
+	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
+	JavaCore.setOptions(options);
+
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	String expected = "mypack1[PACKAGE_REF]{mypack1, mypack1, null, null, null, 49}\n"
+			+ "mypack2[PACKAGE_REF]{mypack2, mypack2, null, null, null, 49}\n" 
+			+ "mypackage[PACKAGE_REF]{mypackage, mypackage, null, null, null, 49}";
+	assertResults(expected, requestor.getResults());
+	JavaCore.setOptions(tmpOld);
+}
+
+public void test486988_0008() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[4];
+	String fileContent =  "module my.mod {"
+			+ "exports mypack1 t"
+			+ "}\n";
+
+	this.workingCopies[0] = getWorkingCopy(
+			"/Completion/src/module-info.java", fileContent);
+
+	this.workingCopies[1] = getWorkingCopy(
+			"/Completion/src/mypack1/Y.java",
+			"package pack1;\n" +
+			"public class Y {\n" +
+			"}");
+
+	this.workingCopies[2] = getWorkingCopy(
+			"/Completion/src/mypack2/Z.java",
+			"package pack2;\n" +
+			"public class Z {\n" +
+			"}");
+
+	this.workingCopies[3] = getWorkingCopy(
+			"/Completion/src/mypack1.mypack2/Z.java",
+			"package mypack1.mypack2;\n" +
+			"public class Z {\n" +
+			"}");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "mypack1 t";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+
+	Hashtable<String, String> tmpOld = JavaCore.getOptions();
+	Hashtable<String, String> options = new Hashtable<>(tmpOld);
+	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
+	JavaCore.setOptions(options);
+
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	String expected = "to[KEYWORD]{to, null, null, to, null, 49}";
+	assertResults(expected, requestor.getResults());
+	JavaCore.setOptions(tmpOld);
+
+}
+public void test486988_0009() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project2.open(null);
+		String fileContent =  "module org.eclipse.foo {}\n";
+		String filePath = "/Completion9_2/src/module-info.java";
+		createFile(filePath, fileContent);
+
+		project1.open(null);
+		filePath = "/Completion9_1/src/module-info.java";
+		fileContent =  "module com.greetings {requires o }\n";
+		createFile(filePath, fileContent);
+		String completeBehind = "requires o";
+		int cursorLocation = fileContent.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "[PROPOSAL]{org.eclipse.foo, org.eclipse.foo, null, null, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+
+public void test486988_0010() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		String filePath = "/Completion9_1/src/module-info.java";
+		String fileContent =  "module com.greetings {"
+				+ "requires org.eclipse.foo;\n"
+				+ "}\n";
+		createFile(filePath, fileContent);
+		project1.close(); //sync
+		project1.open(null);
+
+		project2.open(null);
+		String pack = "/Completion9_2/src/mypack1";
+		createFolder(pack);
+		filePath = pack + "/Y.java";
+		fileContent = "package pack1;\n" +
+		"public class Y {}\n";
+		createFile(filePath, fileContent);
+
+		fileContent =  "module org.eclipse.foo { "
+				+ "exports mypack1 to com"
+				+ "}\n";
+		filePath = "/Completion9_2/src/module-info.java";
+		createFile(filePath, fileContent);
+
+		String completeBehind = "com";
+		int cursorLocation = fileContent.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "[PROPOSAL]{com.greetings, com.greetings, null, null, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+public void test486988_0011() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack12", "X12");
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "pack";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ "uses " + completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;\n"
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "pack11[PACKAGE_REF]{pack11, pack11, null, null, 49}\n"
+				+ "pack12[PACKAGE_REF]{pack12, pack12, null, null, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+public void test486988_0012() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack12", "X12");
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "X1";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ "uses " + completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;"
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "X11[TYPE_REF]{pack11.X11, pack11, Lpack11.X11;, null, 49}\n"
+				+ "X12[TYPE_REF]{pack12.X12, pack12, Lpack12.X12;, null, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+public void test486988_0013() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack12", "X12");
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "X1";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ "provides " + completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;"
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "X11[TYPE_REF]{pack11.X11, pack11, Lpack11.X11;, null, 49}\n"
+				+ "X12[TYPE_REF]{pack12.X12, pack12, Lpack12.X12;, null, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+public void test486988_0014() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack12", "X12");
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "w";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ "provides pack11.X11 " + completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;"
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "with[KEYWORD]{with, null, null, with, 49}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+public void test486988_0015() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack11.packinternal", "Z11");
+		createTypePlus("/Completion9_1/src/", "pack11.packinternal", "Z12", "implements pack22.I22", true /* isClass */, false /* createFolder */);
+		createType("/Completion9_1/src/", "pack12", "X12");
+		createTypePlus("/Completion9_1/src/", "pack12", "Y12", "implements pack22.I22", true /* isClass */, false /* createFolder */);
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "with p";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ "provides pack22.I22 " + completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+		createTypePlus("/Completion9_2/src/", "pack22", "I22", null, false /* isClass */, false /* createFolder */);
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;\n"
+				+ "exports pack22 to first;\n" 
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "pack11[PACKAGE_REF]{pack11, pack11, null, null, 49}\n" + 
+				"pack12[PACKAGE_REF]{pack12, pack12, null, null, 49}"
+				//+ "\nShow me the type Honey!!"
+				;
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
index 89e92bd..3b06c21 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations17Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 GK Software AG, and others.
+ * Copyright (c) 2015, 2016 GK Software AG, and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -58,6 +58,13 @@
 	}
 
 	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
+
+	/**
 	 * @deprecated indirectly uses deprecated class PackageAdmin
 	 */
 	protected Bundle[] getAnnotationBundles() {
@@ -148,7 +155,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(933) Null type mismatch: required '@NonNull String' but the provided value is specified as @Nullable",
@@ -165,7 +172,7 @@
 			}, null);
 		IPackageFragment fragment = this.root.getPackageFragment("test1");
 		ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems,
 					new String[] {
@@ -214,7 +221,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(933) Null type mismatch: required '@NonNull String' but the provided value is specified as @Nullable",
@@ -250,7 +257,7 @@
 				"}\n";
 		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java", test1Content,
 						true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -282,7 +289,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is gone:
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertNoProblems(reconciled.getProblems());		
 	}
 
@@ -312,7 +319,7 @@
 				"}\n";
 		ICompilationUnit cu = fragment.createCompilationUnit("Test1.java", test1Content,
 						true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -344,7 +351,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is even worse now:
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 				"Pb(933) Null type mismatch: required '@NonNull Lib1<String>' but the provided value is specified as @Nullable",
@@ -378,7 +385,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 				"Pb(912) Null type safety: The expression of type 'Lib1<String>' needs unchecked conversion to conform to '@NonNull Lib1<String>'",
@@ -387,7 +394,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Lib1");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -417,7 +424,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error has gone:
-		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertNoProblems(reconciled.getProblems());
 	}
 
@@ -457,7 +464,7 @@
 					"	}\n" +
 					"}\n",
 					true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			IProblem[] problems = reconciled.getProblems();
 			assertProblems(problems, new String[] {
 					"Pb(912) Null type safety: The expression of type 'Lib1<String>' needs unchecked conversion to conform to '@NonNull Lib1<String>'",
@@ -505,7 +512,7 @@
 					"	}\n" +
 					"}\n",
 					true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			IProblem[] problems = reconciled.getProblems();
 			assertProblems(problems, new String[] {
 					"Pb(912) Null type safety: The expression of type 'Lib1<String>' needs unchecked conversion to conform to '@NonNull Lib1<String>'",
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 4d61dc0..726fbf0 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Stephan Herrmann - initial API and implementation
  *******************************************************************************/
@@ -175,6 +179,13 @@
 	}
 
 	/**
+	 * @deprecated
+	 */
+	static int getJLS8() {
+		return AST.JLS8;
+	}
+
+	/**
 	 * @deprecated indirectly uses deprecated class PackageAdmin
 	 */
 	protected Bundle[] getAnnotationBundles() {
@@ -457,7 +468,7 @@
 			}, null);
 		IPackageFragment fragment = this.root.getPackageFragment("test1");
 		ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertNoProblems(problems);
 	}
@@ -520,7 +531,7 @@
 				"	}\n" + 
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertNoProblems(problems);
 	}
@@ -586,7 +597,7 @@
 				"	}\n" + 
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Iterator<@NonNull capture#of ?>'. Type 'Iterator<E>' doesn't seem to be designed with null type annotations in mind",
@@ -647,7 +658,7 @@
 				"	}\n" + 
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(955) Null type safety (type annotations): The expression of type 'String[]' needs unchecked conversion to conform to '@Nullable String @Nullable[]'",
@@ -693,7 +704,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
@@ -744,7 +755,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
@@ -795,7 +806,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
@@ -849,7 +860,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
@@ -896,7 +907,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 			"Pb(953) Null type mismatch (type annotations): required '@NonNull Exception' but this expression has type '@Nullable Exception'",
@@ -973,7 +984,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(955) Null type safety (type annotations): The expression of type 'String' needs unchecked conversion to conform to '@NonNull String'",
 		}, new int[] { 8 });
@@ -981,7 +992,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Lib1");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1010,7 +1021,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is even worse now:
-		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
 		}, new int[] { 8 });
@@ -1044,7 +1055,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(953) Null type mismatch (type annotations): required 'Lib1<Lib1.X,@Nullable String>' but this expression has type 'Lib1<Lib1.@Nullable X,@NonNull String>'",
 		}, new int[] { 7 });
@@ -1052,7 +1063,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Lib1");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1082,7 +1093,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is resolved now:
-		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertNoProblems(reconciled.getProblems());
 	}
 	
@@ -1114,7 +1125,7 @@
 				"	}\n" +
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(910) Null type mismatch: required '@NonNull String' but the provided value is null",
 		}, new int[] { 7 });
@@ -1122,7 +1133,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Lib1");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1152,7 +1163,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is resolved now:
-		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertNoProblems(reconciled.getProblems());
 		
 		// invert annotation:
@@ -1165,7 +1176,7 @@
 		assertTrue("file should exist", annotationFile.exists());
 
 		// check that the error is back now:
-		reconciled = cu.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = cu.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(910) Null type mismatch: required '@NonNull String' but the provided value is null",
 		}, new int[] { 7 });
@@ -1201,7 +1212,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Collectors");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1256,7 +1267,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Collectors");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1308,7 +1319,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Collections");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1362,7 +1373,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Collections");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1417,7 +1428,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Thread");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1472,7 +1483,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Thread");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1527,7 +1538,7 @@
 		// acquire library AST:
 		IType type = this.project.findType("libs.Thread");
 		ICompilationUnit libWorkingCopy = type.getClassFile().getWorkingCopy(this.wcOwner, null);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(libWorkingCopy);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(false);
@@ -1613,7 +1624,7 @@
 					"	}\n" + 
 					"}\n",
 					true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			IProblem[] problems = reconciled.getProblems();
 			assertEquals("number of problems", 4, problems.length);
 
@@ -1628,7 +1639,7 @@
 					"	}\n" + 
 					"}\n",
 					true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled2 = unit2.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled2 = unit2.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			assertNoProblems(reconciled2.getProblems());
 			
 			assertEquals("number of log entries", 0, listener.loggedStatus.size());
@@ -1664,7 +1675,7 @@
 			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
 			IPackageFragment fragment = this.root.getPackageFragment("test1");
 			ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			IProblem[] problems = reconciled.getProblems();
 			assertNoProblems(problems);
 		} finally {
@@ -1707,7 +1718,7 @@
 			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
 			IPackageFragment fragment = this.root.getPackageFragment("test1");
 			ICompilationUnit unit = fragment.getCompilationUnit("Reconcile2.java").getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			IProblem[] problems = reconciled.getProblems();
 			assertNoProblems(problems);
 		} finally {
@@ -1741,7 +1752,7 @@
 			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
 			IPackageFragment fragment = this.root.getPackageFragment("test1");
 			ICompilationUnit unit = fragment.getCompilationUnit("Reconcile3.java").getWorkingCopy(new NullProgressMonitor());
-			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 			assertProblems(reconciled.getProblems(), new String[] {
 					"Pb(964) Null constraint mismatch: The type '@Nullable B' is not a valid substitute for the type parameter '@NonNull R'",
 					"Pb(964) Null constraint mismatch: The type '@Nullable String' is not a valid substitute for the type parameter '@NonNull V'",
@@ -1777,7 +1788,7 @@
 				"	}\n" + 
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
 				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
@@ -1788,7 +1799,7 @@
 				" <T:Ljava/lang/Object;>\n" + 
 				" <T:Ljava/lang/Object;>\n" + 
 				"\n");
-		reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
 		}, new int[] { 8 });
@@ -1841,7 +1852,7 @@
 				"	}\n" + 
 				"}\n",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		assertProblems(reconciled.getProblems(), new String[] {
 				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
 				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib2<@NonNull String>'. Type 'Lib2<T>' doesn't seem to be designed with null type annotations in mind",
@@ -1889,12 +1900,13 @@
 				"}\n" +
 				"",
 				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
-		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(getJLS8(), true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
 				"Pb(149) Dead code"
 			}, new int[] { 7 });
 	}
+	@SuppressWarnings("deprecation")
 	public void testBug507256() throws Exception {
 		myCreateJavaProject("TestLibs");
 		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
@@ -1975,6 +1987,7 @@
 	 * Assert that external annotations configured for project A's library are considered also while compiling dependent project B. 
 	 * Reconcile.
 	 */
+	@SuppressWarnings("deprecation")
 	public void testBug509715reconcile() throws Exception {
 		try {
 			setupJavaProject("Bug509715ProjA");
@@ -1995,6 +2008,7 @@
 		}
 	}
 
+	@SuppressWarnings("deprecation")
 	public void testBug500024dir() throws CoreException, IOException {
 		try {
 			String projectName = "Bug500024";
@@ -2033,6 +2047,7 @@
 		}
 	}
 
+	@SuppressWarnings("deprecation")
 	public void testBug500024jar() throws CoreException, IOException {
 		try {
 			String projectName = "Bug500024";
@@ -2079,6 +2094,7 @@
 		}
 	}
 
+		@SuppressWarnings("deprecation")
 	public void testBug508955() throws CoreException, IOException {
 		myCreateJavaProject("TestLibs");
 		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots",
@@ -2130,6 +2146,7 @@
 		assertNoProblems(problems);
 	}
 
+	@SuppressWarnings("deprecation")
 	public void testBug508955b() throws CoreException, IOException {
 		myCreateJavaProject("TestLibs");
 		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots",
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java
new file mode 100644
index 0000000..dbc8822
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java
@@ -0,0 +1,856 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.core.BinaryModule;
+
+import junit.framework.Test;
+
+public class Java9ElementTests extends AbstractJavaModelTests {
+
+	static {
+//		TESTS_NAMES = new String[] {"testBug510339_002"};
+	}
+
+	public Java9ElementTests(String name) {
+		super(name);
+	}
+	public static Test suite() {
+		return buildModelTestSuite(AbstractCompilerTest.F_9, Java9ElementTests.class);
+	}
+	public void test001() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{}\n";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test002() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{\n" +
+						 "	exports p.q.r;" +
+						 "	exports a.b.c;\n" +
+						 "	requires java.sql;\n" +
+						 "	requires transitive java.desktop;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test003() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  
+						"module my.mod{\n" +
+						 "	exports p.q.r;" +
+						 "	exports a.b.c;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				createFolder("/Java9Elements/src/p/q/r");
+				createFolder("/Java9Elements/src/a/b/c");
+				createFile(	"/Java9Elements/src/p/q/package-info.java",	
+						"/** Javadoc for package p.q */"
+						+ "package p.q;");
+				createFile(	"/Java9Elements/src/a/b/c/package-info.java",	
+						"/** Javadoc for package a.b.c */"
+						+ "package a.b.c;");
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				
+				int start = fileContent.indexOf("p.q");
+				IJavaElement[] elements = unit.codeSelect(start, 3);
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.PACKAGE_FRAGMENT, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", "p.q [in src [in Java9Elements]]", elements[0]);
+
+				start = fileContent.indexOf("a.b.c");
+				elements = unit.codeSelect(start, 5);
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.PACKAGE_FRAGMENT, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", "a.b.c [in src [in Java9Elements]]", elements[0]);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test004() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  
+						"module my.mod{\n" +
+						 "	provides com.socket.spi.NetworkSocketProvider\n" +
+						 "      with org.fastsocket.FastNetworkSocketProvider;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test005() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  
+						"module my.mod{\n" +
+						 "	uses com.socket.spi.NetworkSocketProvider;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test006() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			String fileContent =  
+					"module my.mod{\n" +
+					"	exports p.q.r;" +
+					"	exports a.b.c;\n" +
+					"	requires java.sql;\n" +
+					"	requires transitive java.desktop;\n" +
+					"}";
+			createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+			project = createJavaProject("Java9Elements2", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			fileContent =  "module your.mod{\n" +
+					"	requires my.mod;\n" +
+					"	requires transitive java.desktop;\n" +
+					"}";
+			createFile(	"/Java9Elements2/src/module-info.java",	fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements2/src/module-info.java");
+			int start = fileContent.indexOf("y.mod");
+			IJavaElement[] elements = unit.codeSelect(start, 0);
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertEquals("Incorrect element type", IJavaElement.JAVA_MODULE, elements[0].getElementType());
+			assertEquals("incorrect element name", "my.mod", elements[0].getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("Java9Elements2");
+		}
+	}
+	public void test007() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			String fileContent =  
+					"module my.mod{\n" +
+					"	exports p.q.r;" +
+					"	exports a.b.c;\n" +
+					"}";
+			createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+			project = createJavaProject("Java9Elements2", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			fileContent =  
+					"module your.mod{\n" +
+					"	requires my.mod;\n" +
+					"}";
+			createFile(	"/Java9Elements2/src/module-info.java",	fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements2/src/module-info.java");
+			int start = fileContent.lastIndexOf(".mod");
+			IJavaElement[] elements = unit.codeSelect(start, 0);
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertEquals("Incorrect element type", IJavaElement.JAVA_MODULE, elements[0].getElementType());
+			assertEquals("incorrect element name", "my.mod", elements[0].getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("Java9Elements2");
+		}	
+	}
+	public void test008() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			String fileContent =  "module my.mod {\n" +
+					"	exports p.q.r to your.mod;" +
+					"}";
+			createFolder("/Java9Elements/src/p/q/r");
+			createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+			int start = fileContent.indexOf("your.mod");
+
+			project = createJavaProject("Java9Elements2", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			fileContent =  "module your.mod{\n" +
+					"	requires my.mod;\n" +
+					"}";
+			createFile(	"/Java9Elements2/src/module-info.java",	fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+
+			IJavaElement[] elements = unit.codeSelect(start, 0);
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertEquals("Incorrect element type", IJavaElement.JAVA_MODULE, elements[0].getElementType());
+			assertEquals("incorrect element name", "your.mod", elements[0].getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("Java9Elements2");
+		}	
+	}
+	public void test009() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			String fileContent =  "module my.mod {\n" +
+					"	exports p.q.r;" +
+					"}";
+			createFolder("/Java9Elements/src/p/q/r");
+			createFile("/Java9Elements/src/package-info.java",
+					"package p.q.r;");
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			int start = fileContent.indexOf("r;");
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+
+			IJavaElement[] elements = unit.codeSelect(start, 0);
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertEquals("Incorrect element type", IJavaElement.PACKAGE_FRAGMENT, elements[0].getElementType());
+			assertEquals("incorrect element name", "p.q.r", elements[0].getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}	
+	}
+	public void test010() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+			String fileContent =  "// A very simple module" +
+					 "module my.mod {\n" +
+					"	exports p.q.r;" +
+					"}";
+			createFolder("/Java9Elements/src/p/q/r");
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			int start = fileContent.lastIndexOf("module");
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+
+			IJavaElement[] elements = unit.codeSelect(start, "module".length());
+			assertEquals("Incorrect no of elements", 0, elements.length);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test011() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{" +
+									"	provides a.b.C with a.b.CImpl, a.b.DImpl;\n" + 
+									"	opens a.b;" +
+									"}\n";
+				createFolder("/Java9Elements/src/a/b");
+				createFile("/Java9Elements/src/a/b/C.java",
+						"package a.b;\n" + 
+						"public interface C {}");
+				createFile("/Java9Elements/src/a/b/CImpl.java",
+						"package a.b;\n" + 
+						"public class CImpl implements C {}");
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test012() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{" +
+									"	provides a.b.C with a.b.CImpl, a.b.DImpl;\n" + 
+									"}\n";
+				createFolder("/Java9Elements/src/a/b");
+				createFile("/Java9Elements/src/a/b/C.java",
+						"package a.b;\n" + 
+						"public interface C {}");
+				createFile("/Java9Elements/src/a/b/CImpl.java",
+						"package a.b;\n" + 
+						"public class CImpl implements C {}");
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test013() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{" +
+									"	opens a.b to java.base, java.sql;" +
+									"}\n";
+				createFolder("/Java9Elements/src/a/b");
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test014() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{" +
+									"	exports a.b to java.base, java.sql;" +
+									"}\n";
+				createFolder("/Java9Elements/src/a/b");
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				assertNotNull("Module should not be null", mod);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testBug510339_001_since_9() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			addClasspathEntry(project, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			project.open(null);
+			String fileContent =
+				"module first {\n" +
+				"    exports pack1 to second;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			int start = fileContent.lastIndexOf("pack1");
+			createFolder("/Java9Elements/src/pack1");
+			createFile("/Java9Elements/src/pack1/X11.java",
+					"package pack1;\n" +
+					"public class X11 {}\n");
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+
+			IJavaElement[] elements = unit.codeSelect(start, "pack1".length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IPackageFragment fragment = (IPackageFragment) elements[0];
+			assertEquals("pack1", fragment.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testBug510339_002_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    exports pack1 to second;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			String selection = "second";
+			int start = fileContent.lastIndexOf(selection);
+			createFolder("/Java9Elements/src/pack1");
+			createFile("/Java9Elements/src/pack1/X11.java",
+					"package pack1;\n" +
+					"public class X11 {}\n");
+
+			IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project2.open(null);
+			addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String secondFile =
+					"module second {\n" +
+					"    requires first;\n" +
+					"}\n";
+			createFile("/second/src/module-info.java",	secondFile);
+
+			addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+			project1.close(); // sync
+			project2.close();
+			project2.open(null);
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IModuleDescription ref = (IModuleDescription) elements[0];
+			assertEquals("second", ref.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("second");
+		}
+	}
+	public void testBug510339_003_since_9() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			addClasspathEntry(project, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			project.open(null);
+			String fileContent =
+				"module first {\n" +
+				"    opens pack1 to second;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			int start = fileContent.lastIndexOf("pack1");
+			createFolder("/Java9Elements/src/pack1");
+			createFile("/Java9Elements/src/pack1/X11.java",
+					"package pack1;\n" +
+					"public class X11 {}\n");
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+
+			IJavaElement[] elements = unit.codeSelect(start, "pack1".length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IPackageFragment fragment = (IPackageFragment) elements[0];
+			assertEquals("pack1", fragment.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testBug510339_004_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    exports pack1 to second;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java",	fileContent);
+			createFolder("/Java9Elements/src/pack1");
+			createFile("/Java9Elements/src/pack1/X11.java",
+					"package pack1;\n" +
+					"public class X11 {}\n");
+
+			IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project2.open(null);
+			addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String secondFile =
+					"module second {\n" +
+					"    requires first;\n" +
+					"}\n";
+			createFile("/second/src/module-info.java",	secondFile);
+
+			addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+			project1.close(); // sync
+			project2.close();
+			project2.open(null);
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/second/src/module-info.java");
+			String selection = "first";
+			int start = secondFile.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IModuleDescription ref = (IModuleDescription) elements[0];
+			assertEquals("first", ref.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("second");
+		}
+	}
+	public void testBug510339_005_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    provides pack22.I22 with pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project2.open(null);
+			addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String secondFile =
+					"module second {\n" +
+					"    exports pack22 to first;\n" +
+					"}\n";
+			createFile("/second/src/module-info.java",	secondFile);
+			createFolder("/second/src/pack22");
+			createFile("/second/src/pack22/I22.java",
+					"package pack22;\n" +
+					"public interface I22 {}\n");
+
+			addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+			project1.close(); // sync
+			project2.close();
+			project2.open(null);
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "pack22";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IPackageFragment fragment = (IPackageFragment) elements[0];
+			assertEquals("pack22", fragment.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("second");
+		}
+	}
+	public void testBug510339_006_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    provides pack22.I22 with pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project2.open(null);
+			addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String secondFile =
+					"module second {\n" +
+					"    exports pack22 to first;\n" +
+					"}\n";
+			createFile("/second/src/module-info.java",	secondFile);
+			createFolder("/second/src/pack22");
+			createFile("/second/src/pack22/I22.java",
+					"package pack22;\n" +
+					"public interface I22 {}\n");
+
+			addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+			project1.close(); // sync
+			project2.close();
+			project2.open(null);
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "pack11";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IPackageFragment fragment = (IPackageFragment) elements[0];
+			assertEquals("pack11", fragment.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("second");
+		}
+	}
+	public void testBug510339_007_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    uses pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			project1.close(); // sync
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "pack11";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IPackageFragment fragment = (IPackageFragment) elements[0];
+			assertEquals("pack11", fragment.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testBug510339_008_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    provides pack22.I22 with pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project2.open(null);
+			addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String secondFile =
+					"module second {\n" +
+					"    exports pack22 to first;\n" +
+					"}\n";
+			createFile("/second/src/module-info.java",	secondFile);
+			createFolder("/second/src/pack22");
+			createFile("/second/src/pack22/I22.java",
+					"package pack22;\n" +
+					"public interface I22 {}\n");
+
+			addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+			project1.close(); // sync
+			project2.close();
+			project2.open(null);
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "X11";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IType type = (IType) elements[0];
+			assertEquals("X11", type.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+			deleteProject("second");
+		}
+	}
+	public void testBug510339_009_since_9() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    uses pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			project1.close(); // sync
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "X11";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IType type = (IType) elements[0];
+			assertEquals("X11", type.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testBug510339_010_since_9() throws Exception {
+		try {
+			IJavaProject project1 = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "9");
+			project1.open(null);
+			addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+			String fileContent =
+				"module first {\n" +
+				"    requires second;\n" +
+				"    uses pack11.X11;\n" +
+				"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+			createFolder("/Java9Elements/src/pack11");
+			createFile("/Java9Elements/src/pack11/X11.java",
+					"package pack11;\n" +
+					"public class X11 implements pack22.I22 {}\n");
+
+			project1.close(); // sync
+			project1.open(null);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "X11";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			IType type = (IType) elements[0];
+			assertEquals("X11", type.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void testSystemLibAsJMod() throws Exception {
+		try {
+			IJavaProject project1 = createJava9Project("Java9Elements", new String[] {"src"});
+			project1.open(null);
+			IClasspathEntry[] rawClasspath = project1.getRawClasspath();
+			for (int i = 0; i < rawClasspath.length; i++) {
+				IPath path = rawClasspath[i].getPath();
+				if (path.lastSegment().equals("jrt-fs.jar")) {
+					path = path.removeLastSegments(2).append("jmods").append("java.base.jmod");
+					IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base"));
+					rawClasspath[i] = newEntry;
+				}
+			}
+			project1.setRawClasspath(rawClasspath, null);
+			String fileContent =
+					"module first {\n" +
+					"    requires java.base;\n" +
+					"    uses pack11.X11;\n" +
+					"}\n";
+				createFile("/Java9Elements/src/module-info.java", fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "java.base";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertTrue("Invalid selection result", (elements[0] instanceof BinaryModule));
+			BinaryModule mod = (BinaryModule) elements[0];
+			IPackageExport[] exportedPackages = mod.getExportedPackages();
+			assertNotNull("missing package exports", exportedPackages);
+			assertTrue("missing package exports", exportedPackages.length > 0);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test515342a() throws Exception {
+		try {
+			IJavaProject project = createJavaProject("Java9Elements", new String[] {"src"}, new String[] {"JCL19_LIB"}, "bin", "1.9");
+			project.open(null);
+				String fileContent =  "module my.mod{}\n";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				IModuleDescription mod = unit.getModule();
+				String id = mod.getHandleIdentifier();
+				assertEquals("incorrect id", "=Java9Elements/src<{module-info.java`my.mod", id);
+				IJavaElement element = JavaCore.create(id);
+				assertEquals("incorrect element type", IJavaElement.JAVA_MODULE, element.getElementType());
+				assertEquals("incorrect module name", "my.mod", element.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test515342b() throws Exception {
+		try {
+			IJavaProject project1 = createJava9Project("Java9Elements", new String[] {"src"});
+			project1.open(null);
+			IClasspathEntry[] rawClasspath = project1.getRawClasspath();
+			for (int i = 0; i < rawClasspath.length; i++) {
+				IPath path = rawClasspath[i].getPath();
+				if (path.lastSegment().equals("jrt-fs.jar")) {
+					path = path.removeLastSegments(2).append("jmods").append("java.base.jmod");
+					IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base"));
+					rawClasspath[i] = newEntry;
+				}
+			}
+			project1.setRawClasspath(rawClasspath, null);
+			String fileContent =
+					"module first {\n" +
+							"    requires java.base;\n" +
+							"    uses pack11.X11;\n" +
+							"}\n";
+			createFile("/Java9Elements/src/module-info.java", fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+			String selection = "java.base";
+			int start = fileContent.lastIndexOf(selection);
+			IJavaElement[] elements = unit.codeSelect(start, selection.length());
+			assertEquals("Incorrect no of elements", 1, elements.length);
+			assertTrue("Invalid selection result", (elements[0] instanceof BinaryModule));
+			IModuleDescription mod = (IModuleDescription) elements[0];
+			String id = mod.getHandleIdentifier();
+			assertEquals("incorrect id", "=Java9Elements/C:\\/Java\\/jdk-9-ea+160\\/jmods\\/java.base.jmod<(module-info.class`java.base", id);
+			IJavaElement element = JavaCore.create(id);
+			assertEquals("incorrect element type", IJavaElement.JAVA_MODULE, element.getElementType());
+			assertEquals("incorrect module name", "java.base", element.getElementName());
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
index 713b111..c01aa8f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaConventionTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -200,10 +204,18 @@
 		for (int i = 0; i < invalidNames.length; i++) {
 			assertEquals("compilation unit name not recognized as invalid: " + invalidNames[i], IStatus.ERROR, validate(invalidNames[i], COMPILATION_UNIT_NAME));
 		}
-		String[] validNames = new String[] {"Object.java", "OBJECT.java", "object.java", "package-info.java"};
+		invalidNames = new String[] {"module-package.class"};
+		for (int i = 0; i < invalidNames.length; i++) {
+			assertEquals("compilation unit name not recognized as valid: " + invalidNames[i], IStatus.ERROR, validate(invalidNames[i], CLASS_FILE_NAME));
+		}
+		String[] validNames = new String[] {"Object.java", "OBJECT.java", "object.java", "package-info.java", "module-info.java"};
 		for (int i = 0; i < validNames.length; i++) {
 			assertEquals("compilation unit name not recognized as valid: " + validNames[i], IStatus.OK, validate(validNames[i], COMPILATION_UNIT_NAME));
 		}
+		validNames = new String[] {"module-info.class"};
+		for (int i = 0; i < validNames.length; i++) {
+			assertEquals("compilation unit name not recognized as valid: " + validNames[i], IStatus.OK, validate(validNames[i], CLASS_FILE_NAME));
+		}
 	}
 	/**
 	 * @see JavaConventions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
index 7522813..eb050a5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2015 IBM Corporation and others.
+ * Copyright (c) 2010, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -113,8 +117,10 @@
 	assertTrue(JavaCore.compareJavaVersions("cldc1.1", "1.1") > 0);
 	assertTrue(JavaCore.compareJavaVersions("1.1", "cldc1.1") < 0);
 	assertTrue(JavaCore.compareJavaVersions("1.8", "1.8") == 0);
-	assertTrue(JavaCore.compareJavaVersions("1.8", "1.9") < 0);
-	assertTrue(JavaCore.compareJavaVersions("1.9", "1.8") > 0);
+	assertTrue(JavaCore.compareJavaVersions("1.8", "9") < 0);
+	assertTrue(JavaCore.compareJavaVersions("9", "1.8") > 0);
+	assertTrue(JavaCore.compareJavaVersions("9.0.1", "9.1.2") == 0);
+	assertTrue(JavaCore.compareJavaVersions("9", "9.1.2") == 0);
 }
 }
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
index a15213f..7892136 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - inconsistent initialization of classpath container backed by external class folder, see https://bugs.eclipse.org/320618
@@ -58,7 +62,6 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
-import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -2633,7 +2636,7 @@
 		proj.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
 
 		try {
-			ASTParser parser= ASTParser.newParser(AST.JLS8);
+			ASTParser parser= ASTParser.newParser(AST_INTERNAL_JLS9);
 			parser.setSource(unit);
 			parser.setResolveBindings(true);
 			ASTNode node = parser.createAST(null);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java
new file mode 100644
index 0000000..1287fab
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs9Tests.java
@@ -0,0 +1,499 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.ILocalVariable;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.ReferenceMatch;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.TypeReferenceMatch;
+import junit.framework.Test;
+
+/**
+ * Non-regression tests for bugs fixed in Java Search engine.
+ */
+public class JavaSearchBugs9Tests extends AbstractJavaSearchTests {
+
+	static {
+//	 org.eclipse.jdt.internal.core.search.BasicSearchEngine.VERBOSE = true;
+//	TESTS_NAMES = new String[] {"testBug501162_001"};
+}
+
+public JavaSearchBugs9Tests(String name) {
+	super(name);
+	this.endChar = "";
+}
+public static Test suite() {
+	return buildModelTestSuite(JavaSearchBugs9Tests.class, BYTECODE_DECLARATION_ORDER);
+}
+class TestCollector extends JavaSearchResultCollector {
+	public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException {
+		super.acceptSearchMatch(searchMatch);
+	}
+}
+class ReferenceCollector extends JavaSearchResultCollector {
+	protected void writeLine() throws CoreException {
+		super.writeLine();
+		ReferenceMatch refMatch = (ReferenceMatch) this.match;
+		IJavaElement localElement = refMatch.getLocalElement();
+		if (localElement != null) {
+			this.line.append("+[");
+			if (localElement.getElementType() == IJavaElement.ANNOTATION) {
+				this.line.append('@');
+				this.line.append(localElement.getElementName());
+				this.line.append(" on ");
+				this.line.append(localElement.getParent().getElementName());
+			} else {
+				this.line.append(localElement.getElementName());
+			}
+			this.line.append(']');
+		}
+	}
+
+}
+class TypeReferenceCollector extends ReferenceCollector {
+	protected void writeLine() throws CoreException {
+		super.writeLine();
+		TypeReferenceMatch typeRefMatch = (TypeReferenceMatch) this.match;
+		IJavaElement[] others = typeRefMatch.getOtherElements();
+		int length = others==null ? 0 : others.length;
+		if (length > 0) {
+			this.line.append("+[");
+			for (int i=0; i<length; i++) {
+				IJavaElement other = others[i];
+				if (i>0) this.line.append(',');
+				if (other.getElementType() == IJavaElement.ANNOTATION) {
+					this.line.append('@');
+					this.line.append(other.getElementName());
+					this.line.append(" on ");
+					this.line.append(other.getParent().getElementName());
+				} else {
+					this.line.append(other.getElementName());
+				}
+			}
+			this.line.append(']');
+		}
+	}
+}
+
+IJavaSearchScope getJavaSearchScope() {
+	return SearchEngine.createJavaSearchScope(new IJavaProject[] {getJavaProject("JavaSearchBugs")});
+}
+IJavaSearchScope getJavaSearchScopeBugs(String packageName, boolean addSubpackages) throws JavaModelException {
+	if (packageName == null) return getJavaSearchScope();
+	return getJavaSearchPackageScope("JavaSearchBugs", packageName, addSubpackages);
+}
+public ICompilationUnit getWorkingCopy(String path, String source) throws JavaModelException {
+	if (this.wcOwner == null) {
+		this.wcOwner = new WorkingCopyOwner() {};
+	}
+	return getWorkingCopy(path, source, this.wcOwner);
+}
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.core.tests.model.SuiteOfTestCases#setUpSuite()
+ */
+public void setUpSuite() throws Exception {
+	super.setUpSuite();
+	JAVA_PROJECT = setUpJavaProject("JavaSearchBugs", "9");
+}
+public void tearDownSuite() throws Exception {
+	deleteProject("JavaSearchBugs");
+	super.tearDownSuite();
+}
+protected void setUp () throws Exception {
+	super.setUp();
+	this.resultCollector = new TestCollector();
+	this.resultCollector.showAccuracy(true);
+}
+
+public void _testBug499338_001() throws CoreException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java",
+			"public class X {\n" +
+			"    public static void main(String [] args) throws Exception {\n" +
+			"    	Z z1 = new Z();\n" +
+			"        try (z1;  z1) {\n" +
+			"        }  \n" +
+			"    }  \n" +
+			"}\n" +
+			"class Y implements AutoCloseable {\n" +
+			"	public void close() throws Exception {\n" +
+			"		System.out.println(\"Y CLOSE\");\n" +
+			"	}\n" +
+			"}\n" +
+			"\n" +
+			"class Z implements AutoCloseable {\n" +
+			"	public void close() throws Exception {\n" +
+			"		System.out.println(\"Z CLOSE\");\n" +
+			"	}\n" +
+			"}\n"
+			);
+	String str = this.workingCopies[0].getSource();
+	String selection = "z1";
+	int start = str.indexOf(selection);
+	int length = selection.length();
+	
+	IJavaElement[] elements = this.workingCopies[0].codeSelect(start, length);
+	ILocalVariable local = (ILocalVariable) elements[0];
+	search(local, REFERENCES, EXACT_RULE);
+	assertSearchResults(	
+			"src/X.java void X.main(String[]) [z1] EXACT_MATCH\n" + 
+			"src/X.java void X.main(String[]) [z1] EXACT_MATCH");	
+}
+
+public void testBug501162_001() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first {\n" +
+			"    exports pack1 to second;\n" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 {}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    requires first;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+		
+		IPackageFragment pkg = getPackageFragment("JavaSearchBugs9", "src", "pack1");
+		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] 
+				{getJavaProject("JavaSearchBugs9")});
+
+		search(
+			pkg,
+			ALL_OCCURRENCES,
+			scope,
+			this.resultCollector);
+		assertSearchResults(
+			"src/module-info.java first [pack1] EXACT_MATCH\n" + 
+			"src/pack1 pack1 EXACT_MATCH",
+			this.resultCollector);
+
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+public void testBug501162_002() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first {\n" +
+			"    exports pack1 to second;\n" +
+			"    exports pack1 to third;\n" +
+			"    opens pack1 to fourth;\n" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 {}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    requires first;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+		
+		IPackageFragment pkg = getPackageFragment("JavaSearchBugs9", "src", "pack1");
+		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] 
+				{getJavaProject("JavaSearchBugs9")});
+
+		search(
+			pkg,
+			ALL_OCCURRENCES,
+			scope,
+			this.resultCollector);
+		assertSearchResults(
+			"src/module-info.java first [pack1] EXACT_MATCH\n" + 
+			"src/module-info.java first [pack1] EXACT_MATCH\n" + 
+			"src/module-info.java first [pack1] EXACT_MATCH\n" + 
+			"src/pack1 pack1 EXACT_MATCH",
+			this.resultCollector);
+
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+public void testBug501162_003() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first {\n" +
+			"    requires second;" +
+			"    provides pack22.I22 with pack1.X11;" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 implements pack22.I22{}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    exports pack22 to first;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+		createFolder("/second/src/pack22");
+		createFile("/second/src/pack22/I22.java",
+				"package pack22;\n" +
+				"public interface I22 {}\n");
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		IPackageFragment pkg = getPackageFragment("second", "src", "pack22");
+		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] 
+				{getJavaProject("JavaSearchBugs9")});
+
+		search(
+			pkg,
+			REFERENCES,
+			scope,
+			this.resultCollector);
+		assertSearchResults(
+			"src/module-info.java first [pack22] EXACT_MATCH\n" + 
+			"src/pack1/X11.java pack1.X11 [pack22] EXACT_MATCH\n" + 
+			"src/module-info.java second [pack22] EXACT_MATCH",
+			this.resultCollector);
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+public void testBug501162_005() throws CoreException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/module-info.java",
+			"module first {\n" +
+			"    requires second;" +
+			"    provides pack22.I22 with pack1.X11;" +
+			"}\n"
+			);
+	String str = this.workingCopies[0].getSource();
+	String selection = "first";
+	int start = str.indexOf(selection);
+	int length = selection.length();
+	
+	IJavaElement[] elements = this.workingCopies[0].codeSelect(start, length);
+	IModuleDescription module = (IModuleDescription) elements[0];
+	search(module, ALL_OCCURRENCES, EXACT_RULE);
+	assertSearchResults(	
+			"src/module-info.java first [first] EXACT_MATCH");
+}
+public void testBug501162_006() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first {\n" +
+			"    requires second;" +
+			"    provides pack22.I22 with pack1.X11;" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 implements pack22.I22{}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    exports pack22 to first;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+		createFolder("/second/src/pack1");
+		createFile("/second/src/pack1/I22.java",
+				"package pack22;\n" +
+				"public interface I22 {}\n");
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		SearchPattern pattern = SearchPattern.createPattern("first", IJavaSearchConstants.MODULE, REFERENCES, ERASURE_RULE);
+		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+		search(pattern, scope, this.resultCollector);
+
+		assertSearchResults(
+				"src/module-info.java second [first] EXACT_MATCH",
+			this.resultCollector);
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+public void testBug501162_007() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first.test.org {\n" +
+			"    requires second;" +
+			"    provides pack22.I22 with pack1.X11;" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 implements pack22.I22{}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    exports pack22 to first.test.org;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+		createFolder("/second/src/pack1");
+		createFile("/second/src/pack1/I22.java",
+				"package pack22;\n" +
+				"public interface I22 {}\n");
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		SearchPattern pattern = SearchPattern.createPattern("first.test.org", IJavaSearchConstants.MODULE, REFERENCES, ERASURE_RULE);
+		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] {getJavaProject("JavaSearchBugs9")});
+		search(pattern, scope, this.resultCollector);
+
+		assertSearchResults(
+			"src/module-info.java second [first.test.org] EXACT_MATCH",
+			this.resultCollector);
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+public void testBug501162_008() throws Exception {
+	try {
+
+		IJavaProject project1 = createJavaProject("JavaSearchBugs9", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project1.open(null);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String fileContent = 
+			"module first {\n" +
+			"    requires second;" +
+			"    provides pack22.I22 with pack1.X11;" +
+			"}\n";
+		createFile("/JavaSearchBugs9/src/module-info.java",	fileContent);
+		createFolder("/JavaSearchBugs9/src/pack1");
+		createFile("/JavaSearchBugs9/src/pack1/X11.java",
+				"package pack1;\n" +
+				"public class X11 implements pack22.I22{}\n");
+
+		IJavaProject project2 = createJavaProject("second", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+		project2.open(null);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+		String secondFile = 
+				"module second {\n" +
+				"    exports pack22 to first;\n" +
+				"}\n";
+		createFile("/second/src/module-info.java",	secondFile);
+		createFolder("/second/src/pack1");
+		createFile("/second/src/pack1/I22.java",
+				"package pack22;\n" +
+				"public interface I22 {}\n");
+
+		addClasspathEntry(project1, JavaCore.newProjectEntry(project2.getPath()));
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		SearchPattern pattern = SearchPattern.createPattern("second", IJavaSearchConstants.MODULE, REFERENCES, ERASURE_RULE);
+		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+		search(pattern, scope, this.resultCollector);
+
+		assertSearchResults(
+			"src/module-info.java first [second] EXACT_MATCH",
+			this.resultCollector);
+	}
+	finally {
+		deleteProject("JavaSearchBugs9");
+		deleteProject("second");
+	}
+}
+
+// Add more tests here
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..81a1d8e
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -0,0 +1,2872 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Hashtable;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IProblemRequestor;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.core.util.Messages;
+
+import junit.framework.Test;
+
+public class ModuleBuilderTests extends ModifyingResourceTests {
+	public ModuleBuilderTests(String name) {
+		super(name);
+	}
+
+	static {
+//		 TESTS_NAMES = new String[] { "test_ReconcilerModuleLookup" };
+	}
+	private static boolean isJRE9 = false;
+	protected ProblemRequestor problemRequestor;
+	public static Test suite() {
+		String javaVersion = System.getProperty("java.version");
+		if (javaVersion.length() > 3) {
+			javaVersion = javaVersion.substring(0, 3);
+		}
+		long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion);
+		if (jdkLevel >= ClassFileConstants.JDK9) {
+			isJRE9 = true;
+		}
+		return buildModelTestSuite(ModuleBuilderTests.class, BYTECODE_DECLARATION_ORDER);
+	}
+	public void setUp() throws Exception {
+		super.setUp();
+		this.problemRequestor =  new ProblemRequestor();
+		this.wcOwner = new WorkingCopyOwner() {
+			public IProblemRequestor getProblemRequestor(ICompilationUnit unit) {
+				return ModuleBuilderTests.this.problemRequestor;
+			}
+		};
+	}
+	public void setUpSuite() throws Exception {
+		super.setUpSuite();
+		System.setProperty("modules.to.load", "java.base,java.desktop;java.rmi;java.sql;");
+		this.currentProject = createJava9Project("P1");
+		this.createFile("P1/src/module-info.java", "");
+		this.createFolder("P1/src/com/greetings");
+		this.createFile("P1/src/com/greetings/Main.java", "");
+		waitForManualRefresh();
+		waitForAutoBuild();
+	}
+	// Test that the java.base found as a module package fragment root in the project 
+	public void test001() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = createJava9Project("Test01", new String[]{"src"});
+			this.createFile("Test01/src/module-info.java", "");
+			this.createFolder("Test01/src/com/greetings");
+			this.createFile("Test01/src/com/greetings/Main.java", "");
+			waitForManualRefresh();
+			waitForAutoBuild();
+			project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
+			IPackageFragmentRoot base = null;
+			for (IPackageFragmentRoot iRoot : roots) {
+				IModuleDescription moduleDescription = iRoot.getModuleDescription();
+				if (moduleDescription != null && moduleDescription.getElementName().equals("java.base")) {
+					base = iRoot;
+					break;
+				}
+			}
+			assertNotNull("Java.base module should not null", base);
+			assertMarkers("Unexpected markers", "", project);
+		} finally {
+			deleteProject("Test01");
+		}
+	}
+	// Test the project compiles without errors with a simple module-info.java
+	public void test002() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+							"module M1 {\n" +
+							"	exports com.greetings;\n" +
+							"	requires java.base;\n" +
+							"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			assertMarkers("Unexpected markers", "", this.currentProject);
+		} finally {
+		}
+	}
+	// Test that types from java.base module are seen by the compiler
+	// even without an explicit 'requires java.base' declaration.
+	public void test003() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+							"	exports com.greetings;\n" +
+					"}");
+			this.editFile("P1/src/com/greetings/Main.java",
+					"package com.greetings;\n" +
+					"public class Main {\n" +
+					"	public static void main(String[] args) {\n" +
+					"	}\n" +
+					"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+		}
+	}
+	// Test that a type that is present in the JDK, but not observable to the source module,
+	// is reported as a compilation error.
+	public void test004() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"}");
+			this.editFile("P1/src/com/greetings/Main.java",
+					"package com.greetings;\n" +
+					"import java.sql.Connection;\n" +
+					"public class Main {\n" +
+					"	public Connection con = null;\n" +
+					"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import java.sql cannot be resolved\n" + 
+					"Connection cannot be resolved to a type", markers);
+		} finally {
+		}
+	}
+	// Test that a type that is outside java.base module is available to the compiler
+	// when the module is specified as 'requires'.
+	public void test005() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"	requires java.sql;\n" +
+					"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+		}
+	}
+	// Test that a module that doesn't exist but specified as requires in module-info
+	// doesn't affect rest of the compilation.
+	public void _test006() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"	requires java.sql;\n" +
+					"	requires java.idontexist;\n" +
+					"}");
+			this.editFile("P1/src/com/greetings/Main.java",
+					"package com.greetings;\n" +
+					"public class Main {\n" +
+					"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+		}
+	}
+	private IJavaProject setupP2() throws CoreException {
+		IJavaProject project = createJava9Project("P2");
+		IClasspathEntry projectEntry = 
+				JavaCore.newProjectEntry(new Path("/P1"), true);
+		IClasspathEntry[] old = project.getRawClasspath();
+		IClasspathEntry[] newPath = new IClasspathEntry[old.length +1];
+		System.arraycopy(old, 0, newPath, 0, old.length);
+		newPath[old.length] = projectEntry;
+		project.setRawClasspath(newPath, null);
+		this.editFile("P1/src/module-info.java",
+				"module M1 {\n" +
+				"	exports com.greetings;\n" +
+				"	requires java.base;\n" +
+				"}");
+		this.editFile("P1/src/com/greetings/Main.java",
+				"package com.greetings;\n" +
+				"public class Main {\n" +
+				"	public static void main(String[] args) {\n" +
+				"	}\n" +
+				"}");
+		this.createFile("P2/src/module-info.java",
+				"module M2 {\n" +
+				"	exports org.astro;\n" +
+				"	requires M1;\n" +
+				"}");
+		this.createFolder("P2/src/org/astro");
+		this.createFile("P2/src/org/astro/Test.java",
+				"package org.astro;\n" +
+				"import com.greetings.Main;\n" +
+				"public class Test {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		Main.main(args);\n" +
+				"	}\n" +
+				"}");
+		return project;
+	}
+	/*
+	 * Two Java projects, each with one module. P2 has P1 in its build path but
+	 * module M2 has no 'requires' M1. Should report unresolved type, import etc.  
+	 *
+	 */
+	public void test007() throws Exception {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = setupP2();
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"}");
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	//requires M1;\n" +
+					"}");
+			waitForManualRefresh();
+			project.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import com cannot be resolved\n" + 
+					"Main cannot be resolved", 
+					markers);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	/*
+	 * Two Java project, each with one module. P2 has P1 in its build path and
+	 * module M2 'requires' M1. Should report unresolved type, import etc. But M1
+	 * does not export the package that is used by M2. Test that M2 does not see
+	 * the types in unexported packages.
+	 *
+	 */
+	public void test008() throws Exception {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = setupP2();
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	//exports com.greetings;\n" +
+					"}");
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires M1;\n" +
+					"}");
+			waitForManualRefresh();
+			project.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import com cannot be resolved\n" + 
+					"Main cannot be resolved", 
+					markers);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	/*
+	 * Two Java projects, each with one module. P2 has P1 in its build path.
+	 * Module M2 has "requires M1" in module-info and all packages used by M2 
+	 * are exported by M1. No errors expected. 
+	 */
+	public void test009() throws Exception {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = setupP2();
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"}");
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires M1;\n" +
+					"}");
+			waitForManualRefresh();
+			project.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", 
+					"", markers);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	/*
+	 * Two Java projects, each with a module. Project P2 depends on P1.
+	 * Module M1 exports a package to a specific module, which is not M2.
+	 * Usage of types from M1 in M2 should be reported.
+	 */
+	public void _test010() throws Exception {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = setupP2();
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings to org.main;\n" +
+					"}");
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires M1;\n" +
+					"}");
+			waitForManualRefresh();
+			project.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import com.greetings.Main cannot be resolved\n" + 
+					"Main cannot be resolved", 
+					markers);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	private IJavaProject setupP3() throws CoreException {
+		IJavaProject project = createJava9Project("P3");
+		IClasspathEntry projectEntry = 
+				JavaCore.newProjectEntry(new Path("/P2"), true);
+		IClasspathEntry[] old = project.getRawClasspath();
+		IClasspathEntry[] newPath = new IClasspathEntry[old.length +1];
+		System.arraycopy(old, 0, newPath, 0, old.length);
+		newPath[old.length] = projectEntry;
+		project.setRawClasspath(newPath, null);
+		this.createFile("P3/src/module-info.java",
+				"module M3 {\n" +
+				"	exports org.main;\n" +
+				"	requires M2;\n" +
+				"}");
+		this.createFolder("P3/src/org/main");
+		this.createFile("P3/src/org/main/TestMain.java",
+				"package org.main;\n" +
+				"import com.greetings.*;\n" +
+				"public class TestMain {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		Main.main(args);\n" +
+				"	}\n" +
+				"}");
+		return project;
+	}
+	/*
+	 * Three Java projects, each with one module. Project P3 depends on P2, which depends on P1.
+	 * Module M1 exports a package (to all), M2 requires M1 and M3 requires M2. Usage of types from
+	 * M1 in M3 should be reported as errors.
+	 */
+	public void test011() throws Exception {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"}");
+			IJavaProject p2 = setupP2();
+			IJavaProject p3 = setupP3();
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"The import com cannot be resolved\n" +
+					"Main cannot be resolved",
+					markers);
+		} finally {
+			deleteProject("P2");
+			deleteProject("P3");
+		}
+	}
+	/*
+	 * Three Java projects, each with one module. Project P3 depends on P2, which depends on P1.
+	 * Module M1 exports a package only to M2, M2 requires M1 and M3 requires M2. Usage of types from
+	 * M1 in M3 should not be allowed.
+	 */
+	public void test012() throws Exception {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings to M2;\n" +
+					"}");
+			IJavaProject p2 = setupP2();
+			IJavaProject p3 = setupP3();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import com cannot be resolved\n" + 
+					"Main cannot be resolved", 
+					markers);
+		} finally {
+			deleteProject("P2");
+			deleteProject("P3");
+		}
+	}
+	/*
+	 * Three Java projects, each with one module. Project P3 depends on P2, which depends on P1.
+	 * Module M1 exports a package (to all), M2 requires 'public' M1 and M3 requires M2. Usage of types from
+	 * M1 in M3 should be allowed.
+	 */
+	public void test013() throws Exception {
+		if (!isJRE9) return;
+		try {
+			IJavaProject p2 = setupP2();
+			IJavaProject p3 = setupP3();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("P2");
+			deleteProject("P3");
+		}
+	}
+	/*
+	 * Three Java projects, each with one module. Project P3 depends on P2, which depends on P1.
+	 * Module M1 exports a package only to M2, M2 requires 'public' M1 and M3 requires M2. Usage of types from
+	 * M1 in M3 should be allowed. And no errors reported on M2.
+	 */
+	public void test014() throws Exception {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings to M2;\n" +
+					"}");
+			IJavaProject p2 = setupP2();
+			IJavaProject p3 = setupP3();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("P2");
+			deleteProject("P3");
+		}
+	}
+	public void test015() throws CoreException, IOException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings to M2;\n" +
+					"}");
+			IJavaProject p2 = setupP2();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IFolder folder = getFolder("P1/src");
+			assertNotNull("Should be a module", this.currentProject.getModuleDescription());
+			folder = getFolder("P2/src");
+			folder = getFolder("P1/bin");
+			IPath jarPath = p2.getResource().getLocation().append("m0.jar");
+			org.eclipse.jdt.core.tests.util.Util.zip(new File(folder.getLocation().toOSString()), jarPath.toOSString());
+			IClasspathEntry[] old = p2.getRawClasspath();
+			for (int i = 0; i < old.length; i++) {
+				if (old[i].isExported()) {
+					old[i] = JavaCore.newLibraryEntry(new Path("/P2/m0.jar"), null, null);
+					break;
+				}
+			}
+			p2.setRawClasspath(old, null);
+			p2.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			assertNotNull("Should be a module", p2.getModuleDescription());
+		} finally {
+			deleteProject("P2");
+			deleteProject("P3");
+		}
+	}
+	/*
+	 * Change the module-info and wait for autobuild to 
+	 * report expected errors.
+	 */
+	public void test016() throws CoreException, IOException {
+		if (!isJRE9) return;
+		try {
+			IJavaProject p2 = setupP2();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires java.base;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+			markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"The import com cannot be resolved\n" + 
+					"Main cannot be resolved",  markers);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	/*
+	 * Change the module-info of a required module and wait for autobuild to 
+	 * report expected errors.
+	 */
+	public void test017() throws CoreException, IOException {
+		if (!isJRE9) return;
+		try {
+			IJavaProject p2 = setupP2();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires java.base;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	requires java.base;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+			markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"The import com cannot be resolved\n" + 
+					"Main cannot be resolved",  markers);
+		} finally {
+			deleteProject("P2");
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"}");
+		}
+	}
+	/*
+	 * Change the module-info of a required module and wait for autobuild to 
+	 * report expected errors.
+	 */
+	public void test018() throws CoreException, IOException {
+		if (!isJRE9) return;
+		try {
+			String wkspEncoding = System.getProperty("file.encoding");
+			final String encoding = "UTF-8".equals(wkspEncoding) ? "Cp1252" : "UTF-8";
+			IJavaProject p2 = setupP2();
+			this.editFile("P2/src/module-info.java",
+					"module M2 {\n" +
+					"	exports org.astro;\n" +
+					"	requires java.base;\n" +
+					"	requires transitive M1;\n" +
+					"}");
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			IFile bin = getFile("P1/bin/com/greetings/Main.class");
+			long old = bin.getLocalTimeStamp();
+			IFile file = getFile("P1/src/module-info.java");
+			file.setCharset(encoding, null);
+			waitForManualRefresh();
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+			markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+			long latest = getFile("P1/bin/com/greetings/Main.class").getLocalTimeStamp();
+			assertTrue("Should not have been recompiled", old == latest);
+		} finally {
+			deleteProject("P2");
+		}
+	}
+	/*
+	 * Test that adding or removing java.base does not result in
+	 * re-compilation of module.
+	 */
+	public void _test019() throws CoreException, IOException {
+		if (!isJRE9) return;
+		try {
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"}");
+			waitForManualRefresh();
+			this.currentProject.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.currentProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+			IFile bin = getFile("P1/bin/com/greetings/Main.class");
+			long old = bin.getLocalTimeStamp();
+			waitForManualRefresh();
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"}");
+			this.currentProject.getProject().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
+			long latest = getFile("P1/bin/com/greetings/Main.class").getLocalTimeStamp();
+			assertTrue("Should not have been recompiled", old == latest);
+		} finally {
+			deleteProject("P2");
+			this.editFile("P1/src/module-info.java",
+					"module M1 {\n" +
+					"	exports com.greetings;\n" +
+					"	requires java.base;\n" +
+					"}");
+		}
+	}
+	public void testConvertToModule() throws CoreException, IOException {
+		if (!isJRE9) return;
+		Hashtable<String, String> javaCoreOptions = JavaCore.getOptions();
+		try {
+			IJavaProject project = setUpJavaProject("ConvertToModule", "9");
+			if (!project.getOption("org.eclipse.jdt.core.compiler.compliance", true).equals("9")) {
+				return;
+			}
+			project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
+			IPackageFragmentRoot theRoot = null;
+			for (IPackageFragmentRoot root : roots) {
+				if (root.getElementName().equals("jdt.test")) {
+					theRoot = root;
+					break;
+				}
+			}
+			assertNotNull("should not be null", theRoot);
+			String[] modules = JavaCore.getReferencedModules(project);
+			assertStringsEqual("incorrect result", new String[]{"java.base", "java.desktop", "java.rmi", "java.sql"}, modules);
+		} finally {
+			this.deleteProject("ConvertToModule");
+			 JavaCore.setOptions(javaCoreOptions);
+		}
+	}
+	public void test_services_abstractImpl() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides org.astro.World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public abstract class MyWorld implements World { }\n"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Invalid service implementation, the type com.greetings.MyWorld is abstract", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_invalidImpl() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides org.astro.World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"public class MyWorld { }\n"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Type mismatch: cannot convert from MyWorld to World", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_NoDefaultConstructor() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public MyWorld(String name) { }\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"The service implementation com.greetings.MyWorld must define a public static provider method or a no-arg constructor",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_DefaultConstructorNotVisible() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	MyWorld() { }\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"The no-arg constructor of service implementation com.greetings.MyWorld is not public",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_DuplicateEntries() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Duplicate service entry: org.astro.World",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_NestedClass() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld.Nested;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld {\n" +
+				"	public static class Nested implements World {\n" +
+				"		public String name() {\n" +
+				"			return \" My World!!\";\n" +
+				"		}\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_NonStatic_NestedClass() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld.Nested;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld {\n" +
+				"	public class Nested implements World {\n" +
+				"		public String name() {\n" +
+				"			return \" My World!!\";\n" +
+				"		}\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Invalid service implementation, the type com.greetings.MyWorld.Nested is an inner class",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_ImplDefinedInAnotherModule() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}",
+				"src/org/astro/AstroWorld.java",
+				"package org.astro;\n" +
+				"public class AstroWorld implements World{\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	provides org.astro.World with org.astro.AstroWorld;\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Service implementation org.astro.AstroWorld is not defined in the module with the provides directive",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_ProviderMethod() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyImpl;\n" +
+				"}",
+				"src/com/greetings/MyImpl.java",
+				"package com.greetings;\n" +
+				"public class MyImpl {\n" +
+				"	public static MyWorld provider() {\n" +
+				"		return new MyWorld(\"Name\");\n" +
+				"	}\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public MyWorld(String name) { }\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_ProviderMethod_ReturnTypeFromAnotherModule() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, true);
+			sources = new String[] {
+				"src/module-info.java",
+				"module other.mod {\n" +
+				"	requires org.astro;\n" + 
+				"	exports org.impl;\n" + 
+				"}",
+				"src/org/impl/MyWorld.java",
+				"package org.impl;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("other.mod", sources, true);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	requires other.mod;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyImpl;\n" +
+				"}",
+				"src/com/greetings/MyImpl.java",
+				"package com.greetings;\n" +
+				"import org.impl.MyWorld;\n" +
+				"public class MyImpl {\n" +
+				"	public static MyWorld provider() {\n" +
+				"		return new MyWorld();\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p3 = setupModuleProject("com.greetings", src, true);
+			p3.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("other.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_ProviderMethod_ReturnTypeInvisible() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, true);
+			sources = new String[] {
+				"src/module-info.java",
+				"module other.mod {\n" +
+				"	requires org.astro;\n" + 
+				"}",
+				"src/org/impl/MyWorld.java",
+				"package org.impl;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("other.mod", sources, true);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	requires other.mod;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyImpl;\n" +
+				"}",
+				"src/com/greetings/MyImpl.java",
+				"package com.greetings;\n" +
+				"import org.impl.MyWorld;\n" +
+				"public class MyImpl {\n" +
+				"	public static MyWorld provider() {\n" +
+				"		return new MyWorld();\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p3 = setupModuleProject("com.greetings", src, true);
+			p3.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p3.getProject().getFile(new Path("src/module-info.java")).findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"MyWorld cannot be resolved to a type",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("other.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_ProviderMethod_InvalidReturnType() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyImpl;\n" +
+				"}",
+				"src/com/greetings/MyImpl.java",
+				"package com.greetings;\n" +
+				"public class MyImpl {\n" +
+				"	public static MyWorld provider() {\n" +
+				"		return new MyWorld(\"Name\");\n" +
+				"	}\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"public class MyWorld {\n" +
+				"	public MyWorld(String name) { }\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"Type mismatch: cannot convert from MyWorld to World",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_DuplicateImplEntries() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld, com.greetings.MyWorld;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Duplicate service entry: com.greetings.MyWorld",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_InvalidIntfType() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	exports com.greetings;\n" +
+				"	provides com.greetings.MyEnum with com.greetings.MyEnum;\n" +
+				"}",
+				"src/com/greetings/MyEnum.java",
+				"package com.greetings;\n" +
+				"public enum MyEnum {}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"Invalid service interface com.greetings.MyEnum, must be a class, interface or annotation type\n" +
+					"Invalid service implementation com.greetings.MyEnum, must be a public class or interface type",  markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_InvalidImplType() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyEnum;\n" +
+				"}",
+				"src/com/greetings/MyEnum.java",
+				"package com.greetings;\n" +
+				"public enum MyEnum implements org.astro.World {}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Invalid service implementation com.greetings.MyEnum, must be a public class or interface type",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_services_nonPublicImpl() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"	provides org.astro.World with com.greetings.MyWorld;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"The type com.greetings.MyWorld is not visible",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Exports_Error() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	exports com.greetings;\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"The package com.greetings does not exist or is empty",  markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_DuplicateExports() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"Duplicate exports entry: org.astro",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_TargetedExports_Duplicates() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro to com.greetings, com.greetings;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"Duplicate module name: com.greetings",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// Types from source module should be resolved in target module
+	// when package is exported specifically to the target module
+	public void test_TargetedExports() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro to com.greetings;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// Types in one module should not be visible in target module when
+	// source module exports packages to a specific module which is not
+	// the same as the target module
+	public void test_TargetedExports_Error() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod { }",
+			};
+			setupModuleProject("some.mod", sources);
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro to some.mod;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",	
+					"The import org cannot be resolved\n" +
+					"World cannot be resolved to a type",
+					markers);
+		} finally {
+			deleteProject("some.mod");
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// It is permitted for the to clause of an exports or opens statement to 
+	// specify a module which is not observable
+	public void test_TargetedExports_Unresolved() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro to some.mod;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	// Target module of an exports statement should be resolved without having an explicit
+	// dependency to the project that defines the module
+	public void test_TargetedExports_Resolution() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"}"
+			};
+			setupModuleProject("some.mod", sources);
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro to some.mod;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+		}
+	}
+	// Make sure modules in the workspace are resolved via the module source path container
+	// without needing to add a dependency to the project explicitly
+	public void test_ModuleSourcePathContainer() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// Make sure module path container picks up changes to module-info
+	public void test_ModuleSourcePath_update() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"}"
+			};
+			setupModuleProject("some.mod", sources);
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			this.editFile("com.greetings/src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}");
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	// Implicit module dependencies via the 'requires transitive' directive should be
+	// resolved via the module path container
+	public void test_ModuleSourcePath_implicitdeps() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"	requires transitive org.astro;\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			setupModuleProject("some.mod", sources, new IClasspathEntry[]{dep});
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	// Changes to implicit dependencies should be reflected
+	public void test_ModuleSourcePath_implicitdeps2() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"	requires transitive org.astro;\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			setupModuleProject("some.mod", sources, new IClasspathEntry[]{dep});
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			this.editFile("some.mod/src/module-info.java",
+				"module some.mod {\n" +
+				"	requires org.astro;\n" +
+				"}");
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers", 
+					"The import org cannot be resolved\n" +
+					"World cannot be resolved to a type",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	// Changes to implicit dependencies should be reflected
+	//TODO enable once we know how to update project cache
+	public void _test_ModuleSourcePath_implicitdeps3() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"	requires org.astro;\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			setupModuleProject("some.mod", sources, new IClasspathEntry[]{dep});
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			this.editFile("some.mod/src/module-info.java",
+				"module some.mod {\n" +
+				"	requires transitive org.astro;\n" +
+				"}");
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Cycle_In_Module_Dependency() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"	requires org.astro;\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			setupModuleProject("some.mod", sources, new IClasspathEntry[]{dep});
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"	requires com.greetings;\n" +
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}"
+			};
+			
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			assertTrue("Should detect cycle", p2.hasClasspathCycle(null));
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Cycle_In_Implicit_Module_Dependency() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module some.mod {\n" +
+				"	requires transitive org.astro;\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			setupModuleProject("some.mod", sources, new IClasspathEntry[]{dep});
+			sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"	requires transitive com.greetings;\n" +
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires some.mod;\n" +
+				"	exports com.greetings;\n" +
+				"}"
+			};
+			
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			assertTrue("Should detect cycle", p2.hasClasspathCycle(null));
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("some.mod");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_bug506479() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}"
+				};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			IJavaProject p1 = setupModuleProject("org.astro", sources, new IClasspathEntry[]{dep});
+			IWorkspaceDescription desc = p1.getProject().getWorkspace().getDescription();
+			desc.setAutoBuilding(false);
+			p1.getProject().getWorkspace().setDescription(desc);
+			this.deleteFile("org.astro/src/module-info.java");
+			this.createFile(
+					"org.astro/src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}");
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_Multiple_SourceFolders() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}",
+				"othersrc/org/astro/OtherWorld.java",
+				"package org.astro;\n" +
+				"import org.astro.World;\n" +
+				"public interface OtherWorld {\n" +
+				"	default public String name() {\n" +
+				"		return \" Other World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", new String[]{"src", "othersrc"}, sources, null);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}",
+				"othersrc/com/greetings/AnotherWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.OtherWorld;\n" +
+				"public class AnotherWorld implements OtherWorld {\n" +
+				"	public String name() {\n" +
+				"		return \" Another World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			IJavaProject p2 = setupModuleProject("com.greetings", new String[]{"src", "othersrc"}, src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Multiple_SourceFolders_WithModuleInfo() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}",
+				"othersrc/org/astro/OtherWorld.java",
+				"package org.astro;\n" +
+				"import org.astro.World;\n" +
+				"public interface OtherWorld {\n" +
+				"	default public String name() {\n" +
+				"		return \" Other World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("org.astro", new String[]{"src", "othersrc"}, sources, null);
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}",
+				"othersrc/module-info.java",
+				"module com.greetings1 {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"othersrc/com/greetings/AnotherWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.OtherWorld;\n" +
+				"public class AnotherWorld implements OtherWorld {\n" +
+				"	public String name() {\n" +
+				"		return \" Another World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IClasspathEntry dep = JavaCore.newContainerEntry(new Path(JavaCore.MODULE_PATH_CONTAINER_ID));
+			IJavaProject p2 = setupModuleProject("com.greetings", new String[]{"src", "othersrc"}, src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
+			assertEquals(1, markers.length);
+			String msg = markers[0].getAttribute(IMarker.MESSAGE, "");
+			String expected = Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, p2.getElementName());
+			assertTrue("Unexpected result", msg.indexOf(expected) != -1);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Multiple_SourceFolders_addModuleInfo() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}",
+				"othersrc/org/astro/OtherWorld.java",
+				"package org.astro;\n" +
+				"import org.astro.World;\n" +
+				"public interface OtherWorld {\n" +
+				"	default public String name() {\n" +
+				"		return \" Other World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", new String[]{"src", "othersrc"}, sources, null);
+			this.createFile("org.astro/othersrc/module-info.java", 
+					"module org.astro1 {\n" +
+					"	exports org.astro;\n" + 
+					"}");
+			waitForAutoBuild();
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
+			assertEquals(1, markers.length);
+			String msg = markers[0].getAttribute(IMarker.MESSAGE, "");
+			String expected = Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, p1.getElementName());
+			assertTrue("Unexpected result", msg.indexOf(expected) != -1);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_Multiple_SourceFolders_removeModuleInfo() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}",
+				"othersrc/module-info.java",
+				"module org.astro1 {\n" +
+				"	exports org.astro;\n" + 
+				"}",
+				"othersrc/org/astro/OtherWorld.java",
+				"package org.astro;\n" +
+				"import org.astro.World;\n" +
+				"public interface OtherWorld {\n" +
+				"	default public String name() {\n" +
+				"		return \" Other World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", new String[]{"src", "othersrc"}, sources, null);
+			waitForAutoBuild();
+			this.deleteFile("org.astro/othersrc/module-info.java");
+			waitForAutoBuild();
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
+			assertEquals(0, markers.length);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_services_multipleImpl() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.World;\n" +
+					"import com.greetings.*;\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with MyWorld, AnotherWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}",
+					"src/com/greetings/AnotherWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class AnotherWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" Another World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_imports_in_moduleinfo() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.World;\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+
+	public void test_Opens_Error() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	opens com.greetings;\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"The package com.greetings does not exist or is empty",  markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_DuplicateOpens() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	opens org.astro;\n" + 
+				"	opens org.astro;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"Duplicate opens entry: org.astro",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_TargetedOpens_Duplicates() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	opens org.astro to com.greetings, com.greetings;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires org.astro;\n" +
+				"	exports com.greetings;\n" +
+				"}",
+				"src/com/greetings/MyWorld.java",
+				"package com.greetings;\n" +
+				"import org.astro.World;\n" +
+				"public class MyWorld implements World {\n" +
+				"	public String name() {\n" +
+				"		return \" My World!!\";\n" +
+				"	}\n" +
+				"}"
+			};
+			setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"Duplicate module name: com.greetings",  markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// It is permitted for the to clause of an exports or opens statement to 
+	// specify a module which is not observable
+	public void test_TargetedOpens_Unresolved() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	opens org.astro to some.mod;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	"",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	// It is a compile-time error if an opens statement appears in the declaration of an open module. 
+	public void test_OpensStatment_in_OpenModule() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"open module org.astro {\n" +
+				"	opens org.astro to some.mod;\n" + 
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+				"opens statement is not allowed, as module org.astro is declared open",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_uses_DuplicateEntries() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] {
+				"src/module-info.java",
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"	uses org.astro.World;\n" +
+				"	uses org.astro.World;\n" +
+				"}",
+				"src/org/astro/World.java",
+				"package org.astro;\n" +
+				"public interface World {\n" +
+				"	public String name();\n" +
+				"}"
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			p1.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p1.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Duplicate uses entry: org.astro.World",  markers);
+		} finally {
+			deleteProject("org.astro");
+		}
+	}
+	public void test_uses_InvalidIntfType() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	exports com.greetings;\n" +
+				"	uses com.greetings.MyEnum;\n" +
+				"}",
+				"src/com/greetings/MyEnum.java",
+				"package com.greetings;\n" +
+				"public enum MyEnum {}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"Invalid service interface com.greetings.MyEnum, must be a class, interface or annotation type",  markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_ReconcilerModuleLookup1() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires java.sql;\n" +
+				"}"};
+			setupModuleProject("com.greetings", src);
+			this.workingCopies = new ICompilationUnit[1];
+			char[] sourceChars = src[1].toCharArray();
+			this.problemRequestor.initialize(sourceChars);
+			this.workingCopies[0] = getCompilationUnit("/com.greetings/src/module-info.java").getWorkingCopy(this.wcOwner, null);
+			assertProblems(
+					"Unexpected problems",
+					"----------\n" + 
+					"----------\n",
+					this.problemRequestor);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_ReconcilerModuleLookup2() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	requires java.sq;\n" +
+				"}"};
+			setupModuleProject("com.greetings", src);
+			this.workingCopies = new ICompilationUnit[1];
+			char[] sourceChars = src[1].toCharArray();
+			this.problemRequestor.initialize(sourceChars);
+			this.workingCopies[0] = getCompilationUnit("/com.greetings/src/module-info.java").getWorkingCopy(this.wcOwner, null);
+			assertProblems(
+					"Unexpected problems",
+					"----------\n" + 
+					"1. ERROR in /com.greetings/src/module-info.java (at line 2)\n" + 
+					"	requires java.sq;\n" + 
+					"	         ^^^^^^^\n" + 
+					"java.sq cannot be resolved to a module\n" + 
+					"----------\n",
+					this.problemRequestor);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void testSystemLibAsJMod() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			IJavaProject project = createJava9Project("Test01", new String[]{"src"});
+			IClasspathEntry[] rawClasspath = project.getRawClasspath();
+			for (int i = 0; i < rawClasspath.length; i++) {
+				IPath path = rawClasspath[i].getPath();
+				if (path.lastSegment().equals("jrt-fs.jar")) {
+					path = path.removeLastSegments(2).append("jmods").append("java.base.jmod");
+					IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base"));
+					rawClasspath[i] = newEntry;
+				}
+			}
+			project.setRawClasspath(rawClasspath, null);
+			this.createFile("Test01/src/module-info.java", "");
+			this.createFolder("Test01/src/com/greetings");
+			this.createFile("Test01/src/com/greetings/Main.java", "");
+			waitForManualRefresh();
+			waitForAutoBuild();
+			project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
+			IPackageFragmentRoot base = null;
+			for (IPackageFragmentRoot iRoot : roots) {
+				IModuleDescription moduleDescription = iRoot.getModuleDescription();
+				if (moduleDescription != null) {
+					base = iRoot;
+					break;
+				}
+			}
+			assertNotNull("Java.base module should not null", base);
+			assertMarkers("Unexpected markers", "", project);
+		} finally {
+			deleteProject("Test01");
+		}
+	}
+	public void testBug510617() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module Test {\n" +
+				"	exports p;\n" +
+				"	requires java.sql;\n" + 
+				"	provides java.sql.Driver with p.C;\n" +
+				"}",
+				"src/p/C.java",
+				"package p;\n" + 
+				"import java.lang.SecurityManager;\n" + 
+				"import java.sql.Connection;\n" + 
+				"import java.sql.Driver;\n" + 
+				"import java.sql.DriverPropertyInfo;\n" + 
+				"import java.sql.SQLException;\n" + 
+				"import java.sql.SQLFeatureNotSupportedException;\n" + 
+				"import java.util.Properties;\n" + 
+				"import java.util.logging.Logger;\n" + 
+				"public class C implements Driver {\n" + 
+				"	SecurityManager s;\n" + 
+				"	@Override\n" + 
+				"	public boolean acceptsURL(String arg0) throws SQLException {\n" + 
+				"		return false;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public Connection connect(String arg0, Properties arg1) throws SQLException {\n" + 
+				"		return null;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public int getMajorVersion() {\n" + 
+				"		return 0;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public int getMinorVersion() {\n" + 
+				"		return 0;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n" + 
+				"		return null;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public DriverPropertyInfo[] getPropertyInfo(String arg0, Properties arg1) throws SQLException {\n" + 
+				"		return null;\n" + 
+				"	}\n" + 
+				"	@Override\n" + 
+				"	public boolean jdbcCompliant() {\n" + 
+				"		return false;\n" + 
+				"	} \n" + 
+				"}"
+			};
+			setupModuleProject("Test", src);
+			this.workingCopies = new ICompilationUnit[1];
+			char[] sourceChars = src[1].toCharArray();
+			this.problemRequestor.initialize(sourceChars);
+			this.workingCopies[0] = getCompilationUnit("/Test/src/module-info.java").getWorkingCopy(this.wcOwner, null);
+			assertProblems(
+				"Unexpected problems",
+				"----------\n" + 
+				"----------\n",
+				this.problemRequestor);
+		} finally {
+			deleteProject("Test");
+		}
+	}
+	public void test_annotations_in_moduleinfo() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}",
+					"src/org/astro/Foo.java",
+					"package org.astro;\n" +
+					"public @interface Foo {}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.Foo;\n" +
+					"import org.astro.World;\n" +
+					"@Foo\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_unresolved_annotations() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}",
+					"src/org/astro/Foo.java",
+					"package org.astro;\n" +
+					"public @interface Foo {}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.Foo;\n" +
+					"import org.astro.World;\n" +
+					"@Foo @Bar\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", 
+					"Bar cannot be resolved to a type", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_illegal_modifiers() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}",
+					"src/org/astro/Foo.java",
+					"package org.astro;\n" +
+					"public @interface Foo {}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.Foo;\n" +
+					"import org.astro.World;\n" +
+					"@Foo\n" +
+					"private static module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", 
+					"Illegal modifier for module com.greetings; only open is permitted", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_annotations_with_target() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}",
+					"src/org/astro/Foo.java",
+					"package org.astro;\n" +
+					"import java.lang.annotation.ElementType;\n" +
+					"import java.lang.annotation.Target;\n" +
+					"@Target(ElementType.MODULE)\n" +
+					"public @interface Foo {}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.Foo;\n" +
+					"import org.astro.World;\n" +
+					"@Foo\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_annotations_with_wrong_target() throws CoreException {
+		if (!isJRE9) return;
+		try {
+			String[] sources = new String[] { 
+					"src/module-info.java",
+					"module org.astro {\n" +
+					"	exports org.astro;\n" +
+					"}",
+					"src/org/astro/World.java",
+					"package org.astro;\n" +
+					"public interface World {\n" +
+					"	public String name();\n" +
+					"}",
+					"src/org/astro/Foo.java",
+					"package org.astro;\n" +
+					"import java.lang.annotation.ElementType;\n" +
+					"import java.lang.annotation.Target;\n" +
+					"@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE})\n" +
+					"public @interface Foo {}" 
+			};
+			IJavaProject p1 = setupModuleProject("org.astro", sources);
+			IClasspathEntry dep = JavaCore.newProjectEntry(p1.getPath());
+			String[] src = new String[] { 
+					"src/module-info.java",
+					"import org.astro.Foo;\n" +
+					"import org.astro.World;\n" +
+					"@Foo\n" +
+					"module com.greetings {\n" +
+					"	requires org.astro;\n" +
+					"	exports com.greetings;\n" +
+					"	provides World with com.greetings.MyWorld;\n" +
+					"}",
+					"src/com/greetings/MyWorld.java",
+					"package com.greetings;\n" +
+					"import org.astro.World;\n"	+
+					"public class MyWorld implements World {\n" +
+					"	public String name() {\n" +
+					"		return \" My World!!\";\n" +
+					"	}\n" +
+					"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src, new IClasspathEntry[] { dep });
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", 
+					"The annotation @Foo is disallowed for this location", markers);
+		} finally {
+			deleteProject("org.astro");
+			deleteProject("com.greetings");
+		}
+	}
+	// sort by CHAR_START
+	protected void sortMarkers(IMarker[] markers) {
+		Arrays.sort(markers, (a,b) -> a.getAttribute(IMarker.CHAR_START, 0) - b.getAttribute(IMarker.CHAR_START, 0)); 
+	}
+	public void tearDownSuite() throws Exception {
+		super.tearDownSuite();
+		deleteProject("P1");
+		System.setProperty("modules.on.demand", "");
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
index d36497b..58595ae 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Stephan Herrmann - initial API and implementation
  *******************************************************************************/
@@ -39,7 +43,6 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.MarkerAnnotation;
@@ -294,7 +297,7 @@
 					"Buildpath problem: the type invalid, which is configured as a null annotation type, cannot be resolved\n" +
 					"----------\n");
 
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 			parser.setProject(p);
 			parser.setResolveBindings(true);
 			parser.setSource(unit);
@@ -357,7 +360,7 @@
 			assertEquals("Should have no markers", 0, markers.length);
 
 			// Challenge CompilationUnitResolver:
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 			parser.setProject(p);
 			parser.setResolveBindings(true);
 			parser.setSource(unit);
@@ -428,7 +431,7 @@
 			assertEquals("Unexpected marker path", "/P/p1/C1.java", markers[0].getResource().getFullPath().toString());
 
 			// Challenge CompilationUnitResolver:
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 			parser.setProject(p);
 			parser.setResolveBindings(true);
 			parser.setSource(unit);
@@ -481,7 +484,7 @@
 			final ICompilationUnit unit = getCompilationUnit("/P/p1/C1.java").getWorkingCopy(this.wcOwner, null);
 			assertNoProblem(c1SourceString.toCharArray(), unit);
 
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 			parser.setProject(p);
 			parser.setResolveBindings(true);
 			parser.setSource(unit);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
index 320248b..573dae8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -76,7 +76,7 @@
 		}
 	}
 	
-	/*package*/ static final int JLS_LATEST = AST.JLS8;
+	/*package*/ static final int JLS_LATEST = AST.JLS9;
 
 	static class ReconcileParticipant extends CompilationParticipant {
 		IJavaElementDelta delta;
@@ -87,10 +87,13 @@
 		public boolean isActive(IJavaProject project) {
 			return true;
 		}
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			this.delta = context.getDelta();
 			try {
-				this.ast = context.getAST8();
+				this.ast = context.getAST(JLS_LATEST);
 			} catch (JavaModelException e) {
 				assertNull("Unexpected exception", e);
 			}
@@ -106,10 +109,13 @@
 		public boolean isActive(IJavaProject project) {
 			return true;
 		}
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			this.delta = context.getDelta();
 			try {
-				this.ast = context.getAST8();
+				this.ast = context.getAST(JLS_LATEST);
 				assertTrue("Context should have statement recovery enabled", (context.getReconcileFlags() & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
 				assertTrue("Context should have ignore method body enabled", (context.getReconcileFlags() & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
 			} catch (JavaModelException e) {
@@ -127,10 +133,13 @@
 		public boolean isActive(IJavaProject project) {
 			return true;
 		}
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			this.delta = context.getDelta();
 			try {
-				this.ast = context.getAST8();
+				this.ast = context.getAST(JLS_LATEST);
 				assertFalse("Context should have statement recovery enabled", (context.getReconcileFlags() & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
 				assertTrue("Context should have ignore method body enabled", (context.getReconcileFlags() & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
 			} catch (JavaModelException e) {
@@ -2988,6 +2997,9 @@
  */
 public void testReconcileParticipant05() throws CoreException {
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			try {
 				setWorkingCopyContents(
@@ -3023,6 +3035,9 @@
  */
 public void testReconcileParticipant06() throws CoreException {
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			try {
 				setWorkingCopyContents(
@@ -3106,6 +3121,9 @@
 
 	// reconcile with a participant adding a list of problems
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			context.putProblems("test.marker", new CategorizedProblem[] {});
 		}
@@ -3124,6 +3142,9 @@
 public void testReconcileParticipant09() throws CoreException {
 	this.workingCopy.makeConsistent(null);
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			assertTrue("Participant should not be notified of a reconcile", false);
 		}
@@ -3139,6 +3160,9 @@
 	this.workingCopy.makeConsistent(null);
 	final boolean[] participantReconciled = new boolean[1];
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			participantReconciled[0] = true;
 		}
@@ -3156,6 +3180,9 @@
  */
 public void testReconcileParticipant11() throws CoreException {
 	new ReconcileParticipant() {
+		/**
+		 * @deprecated
+		 */
 		public void reconcile(ReconcileContext context) {
 			context.resetAST();
 		}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
index 66b387c..8c99992 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunCompletionModelTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
@@ -33,6 +37,8 @@
 			COMPLETION_SUITES.add(CompletionTests3.class);
 			COMPLETION_SUITES.add(CompletionTests_1_5.class);
 			COMPLETION_SUITES.add(CompletionTests18.class);
+			// TODO uncomment after bug509050 is done
+			//COMPLETION_SUITES.add(CompletionTests9.class);
 			COMPLETION_SUITES.add(CompletionContextTests.class);
 			COMPLETION_SUITES.add(CompletionContextTests_1_5.class);
 			COMPLETION_SUITES.add(CompletionWithMissingTypesTests.class);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java
index 31e9115..c04d75f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java
@@ -50,7 +50,7 @@
 	ITypeHierarchy typeHierarchy;
 
 static {
-//	TESTS_NAMES= new String[] { "testBug300576" };
+//	TESTS_NAMES= new String[] { "testBug329663a" };
 }
 public static Test suite() {
 	return buildModelTestSuite(TypeHierarchyTests.class, BYTECODE_DECLARATION_ORDER);
@@ -1898,7 +1898,7 @@
 		h.getAllTypes()
 	);
 }
-public void testRegion4() throws CoreException {
+public void _testRegion4() throws CoreException {
 	try {
 		IJavaProject p1 = createJavaProject("P1");
 		IJavaProject p2 = createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "");
@@ -2444,7 +2444,7 @@
  * @throws CoreException
  * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=329663"
  */
-public void testBug329663() throws JavaModelException, CoreException {
+public void _testBug329663() throws JavaModelException, CoreException {
 	try {
 		IJavaProject p1 = createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, new String[0], "");
 		IJavaProject p2 = createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "");
@@ -2491,7 +2491,7 @@
  * @throws CoreException
  * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=329663"
  */
-public void testBug329663a() throws JavaModelException, CoreException {
+public void _testBug329663a() throws JavaModelException, CoreException {
 try {
 	IJavaProject p1 = createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, new String[0], "");
 	IJavaProject p2 = createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "");
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
index fbce7ed..373a4d4 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
@@ -65,6 +65,7 @@
 		return ast.apiLevel() < AST.JLS3 ? INTERNAL_METHOD_RETURN_TYPE_PROPERTY : MethodDeclaration.RETURN_TYPE2_PROPERTY; 
 	} 
 
+	/** @deprecated using deprecated code */
 	private ASTNode createNewExceptionType(AST ast, String name) {
 		return ast.apiLevel() < AST.JLS8 ? ast.newSimpleName(name) : (ASTNode) ast.newSimpleType(ast.newSimpleName(name));
 	}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java
new file mode 100644
index 0000000..240e0d2
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.rewrite.describing;
+
+import java.util.List;
+import junit.framework.Test;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.*;
+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ASTRewritingModuleDeclarationTest extends ASTRewritingTest {
+
+	public ASTRewritingModuleDeclarationTest(String name) {
+		super(name);
+	}
+
+	public ASTRewritingModuleDeclarationTest(String name, int apiLevel) {
+		super(name, apiLevel);
+	}
+
+	public static Test suite() {
+		return createSuite(ASTRewritingModuleDeclarationTest.class);
+	}
+
+	public void testBug509961_0001_since_9() throws Exception {
+		IJavaProject javaProject = null ;
+		try {
+			javaProject = createProject("P_9", JavaCore.VERSION_9);
+			IPackageFragmentRoot currentSourceFolder = getPackageFragmentRoot("P_9", "src");
+			IPackageFragment pack1= currentSourceFolder.getPackageFragment(Util.EMPTY_STRING);
+			StringBuffer buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires second;\n");
+			buf.append("    requires removeme;\n");
+			buf.append("    exports pack11 to third, fourth;\n");
+			buf.append("    exports pack12 to fifth;\n");
+			buf.append("    exports pack12 to remove.mod1;\n");
+			buf.append("    exports pack13 to well.founded.module2;\n");
+			buf.append("    uses MyType;\n");
+			buf.append("    uses Type.Remove;\n");
+			buf.append("    provides pack22.I22 with pack11.packinternal.Z11;\n");
+			buf.append("    provides pack23.I23 with pack11.Z23, pack12.ZZ23;\n");
+			buf.append("}");
+			ICompilationUnit cu= pack1.createCompilationUnit("module-info.java", buf.toString(), false, null);
+			CompilationUnit astRoot= createAST(cu);
+			ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
+			AST ast= astRoot.getAST();
+
+			ModuleDeclaration moduleDecl = astRoot.getModule();
+			ListRewrite listRewrite = rewrite.getListRewrite(moduleDecl, ModuleDeclaration.MODULE_STATEMENTS_PROPERTY);
+			List<ModuleStatement> moduleStatements = moduleDecl.moduleStatements();
+			int index = 0;
+			{
+				RequiresStatement req = (RequiresStatement) moduleStatements.get(index++); // replace the module in first required
+				Name newName = ast.newSimpleName("newSecond");
+				rewrite.replace(req.getName(), newName, null);
+				listRewrite.remove(moduleStatements.get(index++), null); // remove the second required
+
+				RequiresStatement newNode = ast.newRequiresStatement(); // add a new required
+				newNode.setName(ast.newSimpleName("addedme"));
+				listRewrite.insertAfter(newNode, req, null);
+			}
+			{
+				// exports pack11 to third, fourth; -> exports newpack11 to third;
+				ExportsStatement exp = (ExportsStatement) moduleStatements.get(index++);
+				Name newName = ast.newSimpleName("newpack11");
+				rewrite.replace(exp.getName(), newName, null);
+				ListRewrite expListRewrite = rewrite.getListRewrite(exp, ExportsStatement.MODULES_PROPERTY);
+				expListRewrite.remove((ASTNode) exp.modules().get(1), null); 
+
+				// exports pack12 to fifth -> exports pack12 to fifth, sixth
+				exp = (ExportsStatement) moduleStatements.get(index++);
+				newName = ast.newSimpleName("sixth");
+				expListRewrite = rewrite.getListRewrite(exp, ExportsStatement.MODULES_PROPERTY);
+				expListRewrite.insertLast(newName, null);
+
+				// exports pack12 to remove.mod1 -> exports pack12
+				exp = (ExportsStatement) moduleStatements.get(index++);
+				expListRewrite = rewrite.getListRewrite(exp, ExportsStatement.MODULES_PROPERTY);
+				expListRewrite.remove((ASTNode) exp.modules().get(0), null);
+
+				// exports pack12 to never.to.be.module - remove the export
+				listRewrite.remove((ASTNode) moduleDecl.moduleStatements().get(index++), null);
+
+				// exports pack12 to new.found.module - add the export
+				exp = ast.newExportsStatement();
+				exp.setName(ast.newSimpleName("pack12"));
+				Name name = ast.newName("well.founded.module3");
+				exp.modules().add(name);
+				listRewrite.insertLast(exp, null);
+			}
+			{
+				// uses MyType -> uses MyNewType;
+				UsesStatement usesStatement = (UsesStatement) moduleStatements.get(index++);
+				Name newName = ast.newSimpleName("MyNewType");
+				SimpleType type = ast.newSimpleType(newName);
+				rewrite.replace(usesStatement.getType(), type, null);
+
+				// uses Type.Remove - remove the uses
+				listRewrite.remove(moduleStatements.get(index++), null);
+
+				// uses MyNewFoundType - add the uses
+				usesStatement = ast.newUsesStatement();
+				newName = ast.newSimpleName("MyNewFoundType");
+				type = ast.newSimpleType(newName);
+				usesStatement.setType(type);
+				listRewrite.insertLast(usesStatement, null);
+			}
+			{
+				// provides pack22.I22 with pack11.packinternal.Z11 ->  provides pack22.INew22 with pack11.packinternal.NewZ11, pack11.Y11
+				ProvidesStatement providesStatement = (ProvidesStatement) moduleStatements.get(index++);
+				Name newName = ast.newName("pack22.INew22");
+				SimpleType type = ast.newSimpleType(newName);
+				rewrite.replace(providesStatement.getType(), type, null);
+				newName = ast.newName("pack11.packinternal.NewZ11");
+				type = ast.newSimpleType(newName);
+				ListRewrite pListRewrite = rewrite.getListRewrite(providesStatement, ProvidesStatement.IMPLEMENTATIONS_PROPERTY);
+				pListRewrite.replace((ASTNode) providesStatement.implementations().get(0), type ,null);
+
+				newName = ast.newName("pack11.Y11");
+				type = ast.newSimpleType(newName);
+				pListRewrite.insertLast(type, null);
+				// provides pack23.I23 with pack11.Z23, pack12.ZZ23 -> provides pack23.I23 with pack12.ZZ23
+				providesStatement = (ProvidesStatement) moduleStatements.get(index++);
+				pListRewrite = rewrite.getListRewrite(providesStatement, ProvidesStatement.IMPLEMENTATIONS_PROPERTY);
+				pListRewrite.remove((ASTNode) providesStatement.implementations().get(0), null);
+			}
+			String preview= evaluateRewrite(cu, rewrite);
+			buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires newSecond;\n");
+			buf.append("    requires addedme;\n");
+			buf.append("    exports newpack11 to third;\n");
+			buf.append("    exports pack12 to fifth, sixth;\n");
+			buf.append("    exports pack12;\n");
+			buf.append("    uses MyNewType;\n");
+			buf.append("    provides pack22.INew22 with pack11.packinternal.NewZ11, pack11.Y11;\n");
+			buf.append("    provides pack23.I23 with pack12.ZZ23;\n");
+			buf.append("    exports pack12 to well.founded.module3;\n");
+			buf.append("    uses MyNewFoundType;\n");
+			buf.append("}");
+			assertEqualString(preview, buf.toString());
+		} finally {
+			if (javaProject != null)
+				deleteProject(javaProject);
+		}
+	}
+	public void testBug509961_0002_since_9() throws Exception {
+		IJavaProject javaProject = null;
+		try {
+			javaProject = createProject("P_9", JavaCore.VERSION_9);
+			IPackageFragmentRoot currentSourceFolder = getPackageFragmentRoot("P_9", "src");
+			IPackageFragment pack1= currentSourceFolder.getPackageFragment(Util.EMPTY_STRING);
+			StringBuffer buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires existing;\n");
+			buf.append("}");
+
+			ICompilationUnit cu= pack1.createCompilationUnit("module-info.java", buf.toString(), false, null);
+			CompilationUnit astRoot= createAST(cu);
+			ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
+			AST ast= astRoot.getAST();
+
+			ModuleDeclaration moduleDecl = astRoot.getModule();
+			ListRewrite listRewrite = rewrite.getListRewrite(moduleDecl, ModuleDeclaration.MODULE_STATEMENTS_PROPERTY);
+			{
+				RequiresStatement newNode = ast.newRequiresStatement(); // add a new required
+				newNode.setName(ast.newSimpleName("addedme"));
+				listRewrite.insertLast(newNode, null);
+			}
+			String preview= evaluateRewrite(cu, rewrite);
+			buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires existing;\n");
+			buf.append("    requires addedme;\n");
+			buf.append("}");
+			assertEqualString(preview, buf.toString());		
+		} finally {
+			if (javaProject != null) deleteProject(javaProject);
+		}
+	}
+
+	public void testBug509961_0003_since_9() throws Exception {
+		IJavaProject javaProject = null;
+		try {
+			javaProject = createProject("P_9", JavaCore.VERSION_9);
+			IPackageFragmentRoot currentSourceFolder = getPackageFragmentRoot("P_9", "src");
+			IPackageFragment pack1= currentSourceFolder.getPackageFragment(Util.EMPTY_STRING);
+			StringBuffer buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires existing;\n");
+			buf.append("    requires static module1;\n");
+			buf.append("    requires static module2;\n");
+			buf.append("    requires static module3;\n");
+			buf.append("}");
+			ICompilationUnit cu= pack1.createCompilationUnit("module-info.java", buf.toString(), false, null);
+			CompilationUnit astRoot= createAST(cu);
+			ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
+			AST ast= astRoot.getAST();
+			ModuleDeclaration moduleDecl = astRoot.getModule();
+			ListRewrite listRewrite = rewrite.getListRewrite(moduleDecl, ModuleDeclaration.MODULE_STATEMENTS_PROPERTY);
+			{
+				RequiresStatement reqNode = (RequiresStatement) moduleDecl.moduleStatements().get(0);
+				ASTNode newModifier = ast.newModifier(ModifierKeyword.STATIC_KEYWORD);
+				rewrite.getListRewrite(reqNode, RequiresStatement.MODIFIERS_PROPERTY).insertFirst(newModifier, null);
+
+				reqNode = (RequiresStatement) moduleDecl.moduleStatements().get(1);
+				rewrite.getListRewrite(reqNode, RequiresStatement.MODIFIERS_PROPERTY).remove((ASTNode) reqNode.modifiers().get(0), null);
+
+				reqNode = (RequiresStatement) moduleDecl.moduleStatements().get(2);
+				newModifier = ast.newModifier(ModifierKeyword.TRANSIENT_KEYWORD);
+				rewrite.getListRewrite(reqNode, RequiresStatement.MODIFIERS_PROPERTY).replace((ASTNode) reqNode.modifiers().get(0), newModifier, null);
+
+				reqNode = (RequiresStatement) moduleDecl.moduleStatements().get(3);
+				newModifier = ast.newModifier(ModifierKeyword.TRANSIENT_KEYWORD);
+				rewrite.getListRewrite(reqNode, RequiresStatement.MODIFIERS_PROPERTY).insertLast(newModifier, null);
+
+				RequiresStatement newNode = ast.newRequiresStatement(); // add a new required
+				newNode.setName(ast.newSimpleName("addedme"));
+				newModifier = ast.newModifier(ModifierKeyword.TRANSIENT_KEYWORD);
+				rewrite.getListRewrite(newNode, RequiresStatement.MODIFIERS_PROPERTY).insertFirst(newModifier, null);
+				listRewrite.insertLast(newNode, null);
+			}
+			String preview= evaluateRewrite(cu, rewrite);
+			buf= new StringBuffer();
+			buf.append("module first {\n");
+			buf.append("    requires static existing;\n");
+			buf.append("    requires module1;\n");
+			buf.append("    requires transient module2;\n");
+			buf.append("    requires static transient module3;\n");
+			buf.append("    requires transient addedme;\n");
+		buf.append("}");
+			assertEqualString(preview, buf.toString());		
+		} finally {
+			if (javaProject != null) deleteProject(javaProject);
+		}
+	}
+}
\ No newline at end of file
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 3001d4e..b08b3ab 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -30,6 +34,7 @@
 import org.eclipse.jdt.core.dom.BooleanLiteral;
 import org.eclipse.jdt.core.dom.BreakStatement;
 import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.ConstructorInvocation;
@@ -1486,7 +1491,7 @@
 				VariableDeclarationExpression resource = ast.newVariableDeclarationExpression(fragment);
 				resource.setType(ast.newSimpleType(ast.newSimpleName("Reader")));
 
-				rewrite.getListRewrite(newTry, TryStatement.RESOURCES_PROPERTY).insertLast(resource, null);
+				rewrite.getListRewrite(newTry, getResourcesProperty()).insertLast(resource, null);
 	
 				rewrite.replace(doStatement.getBody(), newTry, null);
 			}
@@ -5005,7 +5010,7 @@
 				VariableDeclarationExpression resource = ast.newVariableDeclarationExpression(fragment);
 				resource.setType(ast.newSimpleType(ast.newSimpleName("Reader")));
 
-				rewrite.getListRewrite(tryStatement, TryStatement.RESOURCES_PROPERTY).insertLast(resource, null);
+				rewrite.getListRewrite(tryStatement, getResourcesProperty()).insertLast(resource, null);
 			}
 			{ // replace catch, remove finally
 				TryStatement tryStatement= (TryStatement) blockStatements.get(1);
@@ -5046,6 +5051,12 @@
 			deleteProject("P_17");
 		}
 	}
+	/**
+	 * @deprecated
+	 */
+	protected ChildListPropertyDescriptor getResourcesProperty() {
+		return this.apiLevel < AST_INTERNAL_JLS9 ? TryStatement.RESOURCES_PROPERTY : TryStatement.RESOURCES2_PROPERTY;
+	}
 
 	public void testTryStatementWithResources2_since_4() throws Exception {
 		createProject("P_17", JavaCore.VERSION_1_7);
@@ -5147,7 +5158,7 @@
 					(VariableDeclarationFragment) rewrite.createCopyTarget(fragment));
 			newVariableDeclarationExpression.setType((Type) rewrite.createCopyTarget(variableDeclarationStatement.getType()));
 
-			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, TryStatement.RESOURCES_PROPERTY);
+			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, getResourcesProperty());
 			listRewrite.insertLast(newVariableDeclarationExpression, null);
 			rewrite.remove(variableDeclarationStatement, null);
 
@@ -5225,7 +5236,7 @@
 			VariableDeclarationExpression newVariableDeclarationExpression = ast.newVariableDeclarationExpression(fragment);
 			newVariableDeclarationExpression.setType(ast.newSimpleType(ast.newSimpleName("FileReader")));
 
-			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, TryStatement.RESOURCES_PROPERTY);
+			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, getResourcesProperty());
 			listRewrite.insertLast(newVariableDeclarationExpression, null);
 
 			String preview = evaluateRewrite(cu, rewrite);
@@ -5300,7 +5311,7 @@
 			VariableDeclarationExpression newVariableDeclarationExpression = ast.newVariableDeclarationExpression(fragment);
 			newVariableDeclarationExpression.setType(ast.newSimpleType(ast.newSimpleName("FileReader")));
 
-			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, TryStatement.RESOURCES_PROPERTY);
+			ListRewrite listRewrite = rewrite.getListRewrite(tryStatement, getResourcesProperty());
 			listRewrite.insertLast(newVariableDeclarationExpression, null);
 
 			String preview = evaluateRewrite(cu, rewrite);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
index 2d46ab6..565be69 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -59,7 +63,10 @@
 	/** @deprecated using deprecated code */
 	private final static int JLS4_INTERNAL = AST.JLS4;
 
-	private final static int[] JLS_LEVELS = { JLS2_INTERNAL, JLS3_INTERNAL, JLS4_INTERNAL, AST.JLS8 };
+	/** @deprecated using deprecated code */
+	private final static int JLS8_INTERNAL = AST.JLS8;
+
+	private final static int[] JLS_LEVELS = { JLS2_INTERNAL, JLS3_INTERNAL, JLS4_INTERNAL, JLS8_INTERNAL, AST.JLS9 };
 
 	private static final String ONLY_AST_STRING = "_only";
 	private static final String SINCE_AST_STRING = "_since";
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java
index 750c4e0..ceef7af 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -29,7 +29,13 @@
 	}
 
 	public static Test suite() {
-		return createSuite(ASTRewritingTypeAnnotationsTest.class, AST.JLS8);
+		return createSuite(ASTRewritingTypeAnnotationsTest.class, getAST8());
+	}
+	/**
+	 * @deprecated references deprecated old AST level
+	 */
+	protected static int getAST8() {
+		return AST.JLS8;
 	}
 
 	public void testCastAnnotations() throws Exception {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeDeclTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeDeclTest.java
index 14b716d..7c03739 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeDeclTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeDeclTest.java
@@ -86,7 +86,12 @@
 	public static Test suite() {
 		return createSuite(ASTRewritingTypeDeclTest.class);
 	}
-
+	/**
+	 * @deprecated references deprecated old AST level
+	 */
+	protected static int getAST8() {
+		return AST.JLS8;
+	}
 	/** @deprecated using deprecated code */
 	public void testTypeDeclChanges_only_2() throws Exception {
 		IPackageFragment pack1= this.sourceFolder.createPackageFragment("test1", false, null);
@@ -1940,7 +1945,7 @@
 		buf.append("    interface IC {}\n");
 		buf.append("}\n");
 		ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null);
-		CompilationUnit astRoot= createAST(AST.JLS8, cu, true, false);
+		CompilationUnit astRoot= createAST(getAST8(), cu, true, false);
 		List types = astRoot.types();
 		TypeDeclaration typeDeclaration = (((TypeDeclaration) types.get(0)).getTypes())[0];
 		ITypeBinding iTypeBinding = typeDeclaration.resolveBinding();
@@ -1954,7 +1959,7 @@
 		buf.append("    interface IC {}\n");
 		buf.append("}\n");
 		ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null);
-		CompilationUnit astRoot= createAST(AST.JLS8, cu, true, false);
+		CompilationUnit astRoot= createAST(getAST8(), cu, true, false);
 		List types = astRoot.types();
 		TypeDeclaration outerTypeDeclaration = (TypeDeclaration) types.get(0);
 		TypeDeclaration memberTypeDeclaration = (outerTypeDeclaration.getTypes())[0];
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java
index 34c9db1..db6adec 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2015 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -87,7 +87,12 @@
 
 		waitUntilIndexesReady();
 	}
-
+	/**
+	 * @deprecated
+	 */
+	protected static int getJLS8() {
+		return AST.JLS8;
+	}
 	protected void tearDown() throws Exception {
 		deleteProject(PROJECT);
 		super.tearDown();
@@ -111,7 +116,7 @@
 		createFolder("/" + PROJECT + "/src/pack2/pack3");
 		createFile("/" + PROJECT + "/src/pack2/pack3/B.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -169,7 +174,7 @@
 		createFolder("/" + PROJECT + "/src/pack3/pack4");
 		createFile("/" + PROJECT + "/src/pack3/pack4/B.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -226,7 +231,7 @@
 		createFolder("/" + PROJECT + "/src/pack3/pack4");
 		createFile("/" + PROJECT + "/src/pack3/pack4/B.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -287,7 +292,7 @@
 		createFolder("/" + PROJECT + "/src/pack2");
 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -401,7 +406,7 @@
 		createFolder("/" + PROJECT + "/src/pack4");
 		createFile("/" + PROJECT + "/src/pack4/D1.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -472,7 +477,7 @@
 		createFolder("/" + PROJECT + "/src/pack4");
 		createFile("/" + PROJECT + "/src/pack4/D1.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -526,7 +531,7 @@
 		createFolder("/" + PROJECT + "/src/pack2");
 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -580,7 +585,7 @@
 		createFolder("/" + PROJECT + "/src/pack2");
 		createFile("/" + PROJECT + "/src/pack2/B.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -692,7 +697,7 @@
 				"}";
 		createFile("/" + PROJECT + "/src/pack2/Annot2.java", contents);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
@@ -780,7 +785,7 @@
 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
 
 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(getJLS8());
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
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 1aae1d6..7877192 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
@@ -4956,7 +4956,7 @@
 				"}\n";
 		ICompilationUnit cu = pack1.createCompilationUnit("X.java", contents, false, null);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
@@ -4981,7 +4981,7 @@
 				"}\n";
 		ICompilationUnit cu = pack1.createCompilationUnit("X.java", contents, false, null);
 
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS9);
 		parser.setSource(cu);
 		parser.setResolveBindings(true);
 		parser.setStatementsRecovery(true);
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.classpath
new file mode 100644
index 0000000..b4fec06
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="jdt.test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-9"/>
+	<classpathentry kind="lib" path="m1.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.project b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.project
new file mode 100644
index 0000000..21de489
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ConvertToModule</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/ConvertToModule/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a698e59
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/Dummy.java b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/Dummy.java
new file mode 100644
index 0000000..b458dbd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/Dummy.java
@@ -0,0 +1,4 @@
+
+public class Dummy {
+
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/jdt/test/Bar.java b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/jdt/test/Bar.java
new file mode 100644
index 0000000..baf2102
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/jdt/test/Bar.java
@@ -0,0 +1,35 @@
+package org.eclipse.jdt.test;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+
+public class Bar extends Image {
+
+	@Override
+	public Graphics getGraphics() {
+		return null;
+	}
+
+	@Override
+	public int getHeight(ImageObserver arg0) {
+		return 0;
+	}
+
+	@Override
+	public Object getProperty(String arg0, ImageObserver arg1) {
+		return null;
+	}
+
+	@Override
+	public ImageProducer getSource() {
+		return null;
+	}
+
+	@Override
+	public int getWidth(ImageObserver arg0) {
+		return 0;
+	}
+	
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/test/Foo.java b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/test/Foo.java
new file mode 100644
index 0000000..26c5424
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ConvertToModule/jdt.test/org/eclipse/test/Foo.java
@@ -0,0 +1,12 @@
+package org.eclipse.test;
+
+import java.net.ConnectException;
+import java.sql.Connection;
+
+public class Foo {
+	Connection con = null;
+	public void foo1() throws ConnectException {
+	}
+	public void foo2() throws java.rmi.ConnectException {
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Converter9/.classpath b/org.eclipse.jdt.core.tests.model/workspace/Converter9/.classpath
new file mode 100644
index 0000000..3522bc0
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Converter9/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="var" path="CONVERTER_JCL18_LIB" sourcepath="CONVERTER_JCL18_SRC" rootpath="CONVERTER_JCL_SRCROOT"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Converter9/.project b/org.eclipse.jdt.core.tests.model/workspace/Converter9/.project
new file mode 100644
index 0000000..dc2a4b9
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Converter9/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Converter9</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/Converter9/src/testBug497719_001/X.java b/org.eclipse.jdt.core.tests.model/workspace/Converter9/src/testBug497719_001/X.java
new file mode 100644
index 0000000..634d21b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Converter9/src/testBug497719_001/X.java
@@ -0,0 +1,19 @@
+package testBug497719_001;
+public class X {
+
+    public void foo() throws Exception {
+         final Y y1 = new Y();
+         try (final Y y = new Y(); y1; final Y y2 = new Y()) { 
+        	 //
+         }
+    } 
+    public static void main(String[] args) {
+		System.out.println("Done");
+	}
+}
+class Y implements AutoCloseable {
+    @Override
+    public void close() throws Exception {
+            // nothing
+    }
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_in.java
new file mode 100644
index 0000000..1ee3375
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_in.java
@@ -0,0 +1,13 @@
+module aaaaaaaaaa.bbbbbbbbbb{
+  requires aaaaaaaaaa.cccccccccc; // a      comment
+  requires transitive aaaaaaaaaa
+      .dddddddddd;
+  requires static aaaaaaaaaa.eeeeeeeeee;
+  requires transitive static aaaaaaaaaa.ffffffffff.ggggggggg.hhhhhhhhhh.iiiiiiiiii;
+  exports aaaaaaaaaa.jjjjjjjjjj;
+  exports aaaaaaaaaa.kkkkkkkkkk to aaaaaaaaaa.llllllllll, aaaaaaaaaa.mmmmmmmmmm, aaaaaaaaaa.nnnnnnnnnn;
+  opens aaaaaaaaaa.oooooooooo;
+  opens aaaaaaaaaa.pppppppppp to aaaaaaaaaa.qqqqqqqqqq;
+  uses aaaaaaaaaa.ssssssssss;
+  provides aaaaaaaaaa.tttttttttt with aaaaaaaaaa.uuuuuuuuuu, aaaaaaaaaa.vvvvvvvvvv;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_out.java
new file mode 100644
index 0000000..2fc184a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/A_out.java
@@ -0,0 +1,18 @@
+module aaaaaaaaaa.bbbbbbbbbb {
+	requires aaaaaaaaaa.cccccccccc; // a comment
+	requires transitive aaaaaaaaaa.dddddddddd;
+	requires static aaaaaaaaaa.eeeeeeeeee;
+	requires transitive static aaaaaaaaaa.ffffffffff.ggggggggg.hhhhhhhhhh.iiiiiiiiii;
+
+	exports aaaaaaaaaa.jjjjjjjjjj;
+	exports aaaaaaaaaa.kkkkkkkkkk to aaaaaaaaaa.llllllllll,
+			aaaaaaaaaa.mmmmmmmmmm, aaaaaaaaaa.nnnnnnnnnn;
+
+	opens aaaaaaaaaa.oooooooooo;
+	opens aaaaaaaaaa.pppppppppp to aaaaaaaaaa.qqqqqqqqqq;
+
+	uses aaaaaaaaaa.ssssssssss;
+
+	provides aaaaaaaaaa.tttttttttt
+			with aaaaaaaaaa.uuuuuuuuuu, aaaaaaaaaa.vvvvvvvvvv;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_in.java
new file mode 100644
index 0000000..1ee3375
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_in.java
@@ -0,0 +1,13 @@
+module aaaaaaaaaa.bbbbbbbbbb{
+  requires aaaaaaaaaa.cccccccccc; // a      comment
+  requires transitive aaaaaaaaaa
+      .dddddddddd;
+  requires static aaaaaaaaaa.eeeeeeeeee;
+  requires transitive static aaaaaaaaaa.ffffffffff.ggggggggg.hhhhhhhhhh.iiiiiiiiii;
+  exports aaaaaaaaaa.jjjjjjjjjj;
+  exports aaaaaaaaaa.kkkkkkkkkk to aaaaaaaaaa.llllllllll, aaaaaaaaaa.mmmmmmmmmm, aaaaaaaaaa.nnnnnnnnnn;
+  opens aaaaaaaaaa.oooooooooo;
+  opens aaaaaaaaaa.pppppppppp to aaaaaaaaaa.qqqqqqqqqq;
+  uses aaaaaaaaaa.ssssssssss;
+  provides aaaaaaaaaa.tttttttttt with aaaaaaaaaa.uuuuuuuuuu, aaaaaaaaaa.vvvvvvvvvv;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_out.java
new file mode 100644
index 0000000..ed4da95
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test506430/B_out.java
@@ -0,0 +1,34 @@
+module aaaaaaaaaa.bbbbbbbbbb
+{
+
+
+
+requires aaaaaaaaaa.cccccccccc; // a comment
+
+requires transitive aaaaaaaaaa.dddddddddd;
+
+requires static aaaaaaaaaa.eeeeeeeeee;
+
+requires transitive static aaaaaaaaaa.ffffffffff.ggggggggg.hhhhhhhhhh.iiiiiiiiii;
+
+
+exports aaaaaaaaaa.jjjjjjjjjj;
+
+exports aaaaaaaaaa.kkkkkkkkkk to
+		aaaaaaaaaa.llllllllll ,
+		aaaaaaaaaa.mmmmmmmmmm ,
+		aaaaaaaaaa.nnnnnnnnnn;
+
+
+opens aaaaaaaaaa.oooooooooo;
+
+opens aaaaaaaaaa.pppppppppp to aaaaaaaaaa.qqqqqqqqqq;
+
+
+uses aaaaaaaaaa.ssssssssss;
+
+
+provides aaaaaaaaaa.tttttttttt with
+		aaaaaaaaaa.uuuuuuuuuu ,
+		aaaaaaaaaa.vvvvvvvvvv;
+}
diff --git a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java
index 58878e7..6cf34f9 100644
--- a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java
+++ b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 20157IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -223,6 +227,9 @@
 		public boolean visit(MethodDeclaration node) {
 			return visitNode(node);
 		}
+		public boolean visit(ModuleDeclaration node) {
+			return visitNode(node);
+		}
 		public boolean visit(MethodInvocation node) {
 			return visitNode(node);
 		}
@@ -431,6 +438,9 @@
 		public void endVisit(MethodDeclaration node) {
 			endVisitNode(node);
 		}
+		public void endVisit(ModuleDeclaration node) {
+			endVisitNode(node);
+		}
 		public void endVisit(MethodInvocation node) {
 			endVisitNode(node);
 		}
diff --git a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java
index 91ee0cd..8c7b806 100644
--- a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java
+++ b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceModelTests.java
@@ -42,6 +42,7 @@
 import org.eclipse.jdt.core.IJavaModel;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IProblemRequestor;
@@ -1122,6 +1123,8 @@
 		public boolean isCanceled() {
 			return false;
 		}
+		@Override
+		public void acceptModule(IModuleDescription module) {}
 	}
 
 	// first pass: ensure all class are loaded, and ensure that the test works as expected
diff --git a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/SecondaryTypesPerformanceTest.java b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/SecondaryTypesPerformanceTest.java
index c42b8c8..f1a7950 100644
--- a/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/SecondaryTypesPerformanceTest.java
+++ b/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/SecondaryTypesPerformanceTest.java
@@ -81,7 +81,7 @@
 		classpathList.add(testScratchArea);
 
 		for (int i = 0; i<10; ++i) {
-			ASTParser parser = ASTParser.newParser(AST.JLS8);
+			ASTParser parser = ASTParser.newParser(AST.JLS9);
 			parser.setResolveBindings(true);
 			parser.setStatementsRecovery(true);
 			parser.setBindingsRecovery(true);
diff --git a/org.eclipse.jdt.core/about.html b/org.eclipse.jdt.core/about.html
index c5eab07..681522d 100644
--- a/org.eclipse.jdt.core/about.html
+++ b/org.eclipse.jdt.core/about.html
@@ -8,7 +8,7 @@
 <body lang="EN-US">
 <h2>About This Content</h2>
  
-<p>March 17, 2011</p>
+<p>April 2, 2015</p>
 <h3>License</h3>
 
 <p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
@@ -29,5 +29,10 @@
 use the Disassembler to view the Assembler Mnemonics for a method, you should ensure that doing so will not violate the terms of any licenses that apply to your use of that method, as
 such licenses may not permit you to reverse engineer, decompile, or disassemble method bytecodes.</p>
 
+<h3>Beta Java 9 Support</h3>
+<p>This is an implementation of an early-draft specification developed under the Java
+Community Process (JCP) and is made available for testing and evaluation purposes
+only. The code is not compatible with any specification of the JCP.</p>
+
 </body>
 </html>
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java
new file mode 100644
index 0000000..be313fe
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/BasicModule.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.batch;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.ModuleReferenceImpl;
+import org.eclipse.jdt.internal.compiler.env.PackageExportImpl;
+
+public class BasicModule implements IModule {
+	static class Service implements IModule.IService {
+		char[] provides;
+		char[][] with;
+		@Override
+		public char[] name() {
+			return this.provides;
+		}
+
+		@Override
+		public char[][] with() {
+			return this.with;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append("provides"); //$NON-NLS-1$
+			buffer.append(this.provides);
+			buffer.append(" with "); //$NON-NLS-1$
+			buffer.append(this.with);
+			buffer.append(';');
+			return buffer.toString();
+		}
+	}
+	private static PackageExportImpl createPackageExport(ExportsStatement[] refs, int i) {
+		ExportsStatement ref = refs[i];
+		PackageExportImpl exp = new PackageExportImpl();
+		exp.pack = ref.pkgName;
+		ModuleReference[] imp = ref.targets;
+		if (imp != null) {
+			exp.exportedTo = new char[imp.length][];
+			for(int j = 0; j < imp.length; j++) {
+				exp.exportedTo = imp[j].tokens;
+			}
+		}
+		return exp;
+	}
+	private static Service createService(TypeReference service, TypeReference[] with) {
+		Service ser = new Service();
+		ser.provides = CharOperation.concatWith(service.getTypeName(), '.');
+		ser.with = new char[with.length][];
+		for (int i = 0; i < with.length; i++) {
+			ser.with[i] = CharOperation.concatWith(with[i].getTypeName(), '.');
+		}
+		return ser;
+	}
+	private static PackageExportImpl createPackageOpen(OpensStatement ref) {
+		PackageExportImpl exp = new PackageExportImpl();
+		exp.pack = ref.pkgName;
+		ModuleReference[] imp = ref.targets;
+		if (imp != null) {
+			exp.exportedTo = new char[imp.length][];
+			for(int j = 0; j < imp.length; j++) {
+				exp.exportedTo = imp[j].tokens;
+			}
+		}
+		return exp;
+	}
+
+	boolean isAutomodule;
+	char[] name;
+	IModule.IModuleReference[] requires;
+	IModule.IPackageExport[] exports;
+	char[][] uses;
+	Service[] provides;
+	IModule.IPackageExport[] opens;
+	public BasicModule(ModuleDeclaration descriptor, IModulePathEntry root) {
+		this.name = descriptor.moduleName;
+		if (descriptor.requiresCount > 0) {
+			RequiresStatement[] refs = descriptor.requires;
+			this.requires = new ModuleReferenceImpl[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				ModuleReferenceImpl ref = new ModuleReferenceImpl();
+				ref.name = CharOperation.concatWith(refs[i].module.tokens, '.');
+				ref.modifiers = refs[i].modifiers;
+				this.requires[i] = ref;
+			}
+		} else {
+			this.requires = new ModuleReferenceImpl[0];
+		}
+		if (descriptor.exportsCount > 0) {
+			ExportsStatement[] refs = descriptor.exports;
+			this.exports = new PackageExportImpl[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				PackageExportImpl exp = createPackageExport(refs, i);
+				this.exports[i] = exp;
+			}
+		} else {
+			this.exports = new PackageExportImpl[0];
+		}
+		if (descriptor.usesCount > 0) {
+			UsesStatement[] u = descriptor.uses;
+			this.uses = new char[u.length][];
+			for(int i = 0; i < u.length; i++) {
+				this.uses[i] = CharOperation.concatWith(u[i].serviceInterface.getTypeName(), '.');
+			}
+		}
+		if (descriptor.servicesCount > 0) {
+			ProvidesStatement[] services = descriptor.services;
+			this.provides = new Service[descriptor.servicesCount];
+			for (int i = 0; i < descriptor.servicesCount; i++) {
+				this.provides[i] = createService(services[i].serviceInterface, services[i].implementations);
+			}
+		}
+		if (descriptor.opensCount > 0) {
+			OpensStatement[] refs = descriptor.opens;
+			this.opens = new PackageExportImpl[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				PackageExportImpl exp = createPackageOpen(refs[i]);
+				this.opens[i] = exp;
+			}
+		} else {
+			this.opens = new PackageExportImpl[0];
+		}
+		this.isAutomodule = false; // Just to be explicit
+	}
+	public BasicModule(char[] name, boolean isAuto) {
+		this.name = name;
+		this.exports = IModule.NO_EXPORTS;
+		this.requires = IModule.NO_MODULE_REFS;
+		this.isAutomodule = isAuto;
+	}
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+	@Override
+	public IModule.IModuleReference[] requires() {
+		return this.requires;
+	}
+	@Override
+	public IModule.IPackageExport[] exports() {
+		return this.exports;
+	}
+	@Override
+	public char[][] uses() {
+		return this.uses;
+	}
+	@Override
+	public IService[] provides() {
+		return this.provides;
+	}
+	@Override
+	public IModule.IPackageExport[] opens() {
+		return this.opens;
+	}
+	@Override
+	public boolean isAutomatic() {
+		return this.isAutomodule;
+	}
+	public void addReads(char[] modName) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n));
+		};
+		if (shouldAdd.test(modName)) {
+			int len = this.requires.length;
+			this.requires = Arrays.copyOf(this.requires, len + 1);
+			ModuleReferenceImpl info = new ModuleReferenceImpl();
+			info.name = modName;
+			this.requires[len] = info;
+		}		
+	}
+	public void addExports(IModule.IPackageExport[] toAdd) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.exports).map(ref -> ((PackageExportImpl) ref).pack).noneMatch(n -> CharOperation.equals(m, n));
+		};
+		Collection<IPackageExport> merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd)
+				.filter(e -> shouldAdd.test(e.name()))
+				.map(e -> {
+					PackageExportImpl exp = new PackageExportImpl();
+					exp.pack = ((PackageExportImpl )e).name();
+					exp.exportedTo = ((PackageExportImpl )e).targets();
+					return exp;
+				}))
+			.collect(
+				ArrayList::new,
+				ArrayList::add,
+				ArrayList::addAll);
+		this.exports = merged.toArray(new PackageExportImpl[merged.size()]);
+	}
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (!(o instanceof IModule))
+			return false;
+		IModule mod = (IModule) o;
+		if (!CharOperation.equals(this.name, mod.name()))
+			return false;
+		return Arrays.equals(this.requires, mod.requires());
+	}
+	@Override
+	public int hashCode() {
+		int result = 17;
+		int c = this.name.hashCode();
+		result = 31 * result + c;
+		c =  Arrays.hashCode(this.requires);
+		result = 31 * result + c;
+		return result;
+	}
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(getClass().getName());
+		toStringContent(buffer);
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer) {
+		buffer.append("\nmodule "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append('\n');
+		if (this.requires != null) {
+			for(int i = 0; i < this.requires.length; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (this.requires[i].isTransitive()) {
+					buffer.append(" public "); //$NON-NLS-1$
+				}
+				buffer.append(this.requires[i].name());
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.exports != null) {
+			buffer.append('\n');
+			for(int i = 0; i < this.exports.length; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(this.exports[i].toString());
+			}
+		}
+		if (this.uses != null) {
+			buffer.append('\n');
+			for (char[] cs : this.uses) {
+				buffer.append(cs);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.provides != null) {
+			buffer.append('\n');
+			for(Service ser : this.provides) {
+				buffer.append(ser.toString());
+			}
+		}
+		buffer.append('\n').append('}').toString();
+	}
+}
\ No newline at end of file
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 0ff1a5b..10c78ff 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -23,8 +27,13 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment.AutoModule;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
@@ -40,7 +49,7 @@
 import java.util.Map;
 
 @SuppressWarnings({"rawtypes", "unchecked"})
-public class ClasspathDirectory extends ClasspathLocation {
+public class ClasspathDirectory extends ClasspathLocation implements IModuleEnvironment {
 
 private Hashtable directoryCache;
 private String[] missingPackageHolder = new String[1];
@@ -108,17 +117,15 @@
 public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
 	return null;
 }
-public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
-	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
-}
-public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+private NameEnvironmentAnswer findClassInternal(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
 	if (!isPackage(qualifiedPackageName)) return null; // most common case
-
 	String fileName = new String(typeName);
 	boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + SUFFIX_STRING_class, qualifiedPackageName);
 	boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + SUFFIX_STRING_java, qualifiedPackageName);
 	if (sourceExists && !asBinaryOnly) {
 		String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java;
+		CompilationUnit unit = new CompilationUnit(null, fullSourcePath, this.encoding, this.destinationPath);
+		unit.module = this.module == null ? null : this.module.name();
 		if (!binaryExists)
 			return new NameEnvironmentAnswer(new CompilationUnit(null,
 					fullSourcePath, this.encoding, this.destinationPath),
@@ -141,10 +148,12 @@
 			if (!CharOperation.equals(reader.getName(), typeSearched.toCharArray())) {
 				reader = null;
 			}
-			if (reader != null)
+			if (reader != null) {
+				reader.moduleName = this.module == null ? null : this.module.name();
 				return new NameEnvironmentAnswer(
 						reader,
 						fetchAccessRestriction(qualifiedBinaryFileName));
+			}
 		} catch (IOException e) {
 			// treat as if file is missing
 		} catch (ClassFormatException e) {
@@ -173,8 +182,16 @@
 	}
 	return false;
 }
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+	if (File.separatorChar == '/')
+      return findClassInternal(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
 
-
+	return findClassInternal(typeName, qualifiedPackageName.replace('/', File.separatorChar),
+				qualifiedBinaryFileName.replace('/', File.separatorChar), asBinaryOnly);
+}
 /**
  *  Add all the secondary types in the package
  */
@@ -233,7 +250,7 @@
 }
 
 
-public char[][][] findTypeNames(String qualifiedPackageName) {
+public char[][][] findTypeNames(String qualifiedPackageName, IModule mod) {
 	if (!isPackage(qualifiedPackageName)) {
 		return null; // most common case
 	}
@@ -264,7 +281,8 @@
 	// nothing to do
 }
 public boolean isPackage(String qualifiedPackageName) {
-	return directoryList(qualifiedPackageName) != null;
+	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+	return directoryList(qp2) != null;
 }
 public void reset() {
 	this.directoryCache = new Hashtable(11);
@@ -287,4 +305,29 @@
 public int getMode() {
 	return this.mode;
 }
+public IModule getModule() {
+	if (this.isAutoModule && this.module == null) {
+		return this.module = new AutoModule(this.path.toCharArray());
+	}
+	return this.module;
+}
+@Override
+public ITypeLookup typeLookup() {
+	return this::findClass;
+}
+
+@Override
+public IPackageLookup packageLookup() {
+	return this::isPackage;
+}
+@Override
+public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+	//
+	return this.module == mod ? this : null;
+}
+@Override
+public IModuleEnvironment getLookupEnvironment() {
+	// 
+	return this;
+}
 }
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 ea7baa5..d043886 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -18,9 +22,10 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -30,21 +35,26 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment.AutoModule;
 import org.eclipse.jdt.internal.compiler.util.ManifestAnalyzer;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 @SuppressWarnings({"rawtypes", "unchecked"})
-public class ClasspathJar extends ClasspathLocation {
+public class ClasspathJar extends ClasspathLocation implements IModuleEnvironment {
 
 protected File file;
 protected ZipFile zipFile;
 protected ZipFile annotationZipFile;
 protected boolean closeZipFileAtEnd;
-protected Hashtable packageCache;
+private Set<String> packageCache;
 protected List<String> annotationPaths;
 
 public ClasspathJar(File file, boolean closeZipFileAtEnd,
@@ -80,12 +90,15 @@
 				int lastSeparator = directoryPath.lastIndexOf(File.separatorChar);
 				directoryPath = directoryPath.substring(0, lastSeparator + 1); // potentially empty (see bug 214731)
 				while (calledFilesIterator.hasNext()) {
-					result.add(new ClasspathJar(new File(directoryPath + (String) calledFilesIterator.next()), this.closeZipFileAtEnd, this.accessRuleSet, this.destinationPath));
+						result.add(new ClasspathJar(new File(directoryPath + (String) calledFilesIterator.next()),
+								this.closeZipFileAtEnd, this.accessRuleSet, this.destinationPath));
 				}
 			}
 		}
 		return result;
-	} catch (IOException e) {
+	} catch (IOException | IllegalArgumentException e) {
+		// JRE 9 could throw an IAE if the path is incorrect. We are to ignore such
+		// linked jars
 		return null;
 	} finally {
 		if (inputStream != null) {
@@ -107,6 +120,13 @@
 	try {
 		IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
 		if (reader != null) {
+			char[] modName = this.module == null ? null : this.module.name();
+			if (reader instanceof ClassFileReader) {
+				ClassFileReader classReader = (ClassFileReader) reader;
+				if (classReader.moduleName == null) {
+					classReader.moduleName = modName;
+				}
+			}
 			searchPaths:
 			if (this.annotationPaths != null) {
 				String qualifiedClassName = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length()-SuffixConstants.EXTENSION_CLASS.length()-1);
@@ -127,7 +147,7 @@
 				// location is configured for external annotations, but no .eea found, decorate in order to answer NO_EEA_FILE:
 				reader = new ExternalAnnotationDecorator(reader, null);
 			}
-			return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName));
+			return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), modName);
 		}
 	} catch(ClassFormatException e) {
 		// treat as if class file is missing
@@ -140,67 +160,90 @@
 public boolean hasAnnotationFileFor(String qualifiedTypeName) {
 	return this.zipFile.getEntry(qualifiedTypeName+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX) != null; 
 }
-public char[][][] findTypeNames(String qualifiedPackageName) {
+public char[][][] findTypeNames(final String qualifiedPackageName, final IModule mod) {
 	if (!isPackage(qualifiedPackageName))
 		return null; // most common case
+	final char[] packageArray = qualifiedPackageName.toCharArray();
+	final ArrayList answers = new ArrayList();
+	
+		nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
+			String fileName = ((ZipEntry) e.nextElement()).getName();
 
-	ArrayList answers = new ArrayList();
-	nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
-		String fileName = ((ZipEntry) e.nextElement()).getName();
-
-		// add the package name & all of its parent packages
-		int last = fileName.lastIndexOf('/');
-		while (last > 0) {
-			// extract the package name
-			String packageName = fileName.substring(0, last);
-			if (!qualifiedPackageName.equals(packageName))
-				continue nextEntry;
-			int indexOfDot = fileName.lastIndexOf('.');
-			if (indexOfDot != -1) {
-				String typeName = fileName.substring(last + 1, indexOfDot);
-				char[] packageArray = packageName.toCharArray();
-				answers.add(
-					CharOperation.arrayConcat(
-						CharOperation.splitOn('/', packageArray),
-						typeName.toCharArray()));
+			// add the package name & all of its parent packages
+			int last = fileName.lastIndexOf('/');
+			if (last > 0) {
+				// extract the package name
+				String packageName = fileName.substring(0, last);
+				if (!qualifiedPackageName.equals(packageName))
+					continue nextEntry;
+				addTypeName(answers, fileName, last, packageArray);
 			}
 		}
-	}
 	int size = answers.size();
 	if (size != 0) {
 		char[][][] result = new char[size][][];
 		answers.toArray(result);
-		return null;
+		return result;
 	}
 	return null;
 }
+
+protected void addTypeName(final ArrayList answers, String fileName, int last, char[] packageName) {
+	int indexOfDot = fileName.lastIndexOf('.');
+	if (indexOfDot != -1) {
+		String typeName = fileName.substring(last + 1, indexOfDot);
+		answers.add(
+			CharOperation.arrayConcat(
+				CharOperation.splitOn('/', packageName),
+				typeName.toCharArray()));
+	}
+}
 public void initialize() throws IOException {
 	if (this.zipFile == null) {
 		this.zipFile = new ZipFile(this.file);
 	}
 }
-public boolean isPackage(String qualifiedPackageName) {
-	if (this.packageCache != null)
-		return this.packageCache.containsKey(qualifiedPackageName);
-
-	this.packageCache = new Hashtable(41);
-	this.packageCache.put(Util.EMPTY_STRING, Util.EMPTY_STRING);
-
-	nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
-		String fileName = ((ZipEntry) e.nextElement()).getName();
-
-		// add the package name & all of its parent packages
-		int last = fileName.lastIndexOf('/');
-		while (last > 0) {
-			// extract the package name
-			String packageName = fileName.substring(0, last);
-			if (this.packageCache.containsKey(packageName))
-				continue nextEntry;
-			this.packageCache.put(packageName, packageName);
-			last = packageName.lastIndexOf('/');
-		}
+void acceptModule(ClassFileReader reader) {
+	if (reader != null) {
+		acceptModule(reader.getModuleDeclaration());
 	}
-	return this.packageCache.containsKey(qualifiedPackageName);
+}
+void acceptModule(byte[] content) {
+	if (content == null) 
+		return;
+	ClassFileReader reader = null;
+	try {
+		reader = new ClassFileReader(content, IModuleEnvironment.MODULE_INFO_CLASS.toCharArray(), null);
+	} catch (ClassFormatException e) {
+		e.printStackTrace();
+	}
+	if (reader != null && reader.getModuleDeclaration() != null) {
+		acceptModule(reader);
+	}
+}
+protected void addToPackageCache(String fileName, boolean endsWithSep) {
+	int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/');
+	while (last > 0) {
+		// extract the package name
+		String packageName = fileName.substring(0, last);
+		if (this.packageCache.contains(packageName))
+			return;
+		this.packageCache.add(packageName);
+		last = packageName.lastIndexOf('/');
+	}
+}
+public synchronized boolean isPackage(String qualifiedPackageName) {
+	if (this.packageCache != null)
+		return this.packageCache.contains(qualifiedPackageName);
+
+	this.packageCache = new HashSet<>(41);
+	this.packageCache.add(Util.EMPTY_STRING);
+	
+	for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
+		String fileName = ((ZipEntry) e.nextElement()).getName();
+		addToPackageCache(fileName, false);
+	}
+	return this.packageCache.contains(qualifiedPackageName);
 }
 public void reset() {
 	if (this.closeZipFileAtEnd) {
@@ -221,7 +264,10 @@
 			this.annotationZipFile = null;
 		}
 	}
-	this.packageCache = null;
+	if (this.annotationPaths != null) {
+		this.packageCache = null;
+		this.annotationPaths = null;
+	}
 }
 public String toString() {
 	return "Classpath for jar file " + this.file.getPath(); //$NON-NLS-1$
@@ -251,4 +297,31 @@
 public int getMode() {
 	return BINARY;
 }
+
+public IModule getModule() {
+	if (this.isAutoModule && this.module == null) {
+		return this.module = new AutoModule(this.file.getName().toCharArray());
+	}
+	return this.module;
+}
+@Override
+public ITypeLookup typeLookup() {
+	return this::findClass;
+}
+@Override
+public IPackageLookup packageLookup() {
+	return this::isPackage;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+	// 
+	return servesModule(mod.name()) ? this : null;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironment() {
+	// 
+	return this;
+}
 }
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
new file mode 100644
index 0000000..c40a0bb
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
@@ -0,0 +1,396 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IMultiModuleEntry;
+import org.eclipse.jdt.internal.compiler.env.IMultiModulePackageLookup;
+import org.eclipse.jdt.internal.compiler.env.IMultiModuleTypeLookup;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry, IModuleEnvironment {
+	protected File file;
+	protected ZipFile annotationZipFile;
+	protected boolean closeZipFileAtEnd;
+	private static HashMap<String, Set<IModule>> ModulesCache = new HashMap<>();
+	//private Set<String> packageCache;
+	protected List<String> annotationPaths;
+
+	protected ITypeLookup typeLookupForModule(char[] modName) {
+		return (typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly) -> {
+			return typeLookup().findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly,
+					modName);
+		};
+	}
+
+	protected IPackageLookup pkgLookupForModule(char[] modName) {
+		return qualifiedPackageName -> {
+			return packageLookup().isPackage(qualifiedPackageName, modName);
+		};
+	}
+	public ClasspathJrt(File file, boolean closeZipFileAtEnd,
+			AccessRuleSet accessRuleSet, String destinationPath) {
+		super(accessRuleSet, destinationPath);
+		this.file = file;
+		this.closeZipFileAtEnd = closeZipFileAtEnd;
+	}
+
+	public List fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
+		return null;
+	}
+	public boolean isPackage(String qualifiedPackageName, Optional<char[]> mod) {
+		return JRTUtil.isPackage(this.file, qualifiedPackageName, mod);
+	}
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false, Optional.empty());
+	}
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		return typeLookup().findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly, Optional.empty());
+	}
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, Optional<Collection<char[]>> mods) {
+		if (!isPackage(qualifiedPackageName))
+			return null; // most common case
+
+		try {
+			IBinaryType reader = ClassFileReader.readFromModules(this.file, qualifiedBinaryFileName, mods);
+
+			if (reader != null) {
+				if (this.annotationPaths != null) {
+					String qualifiedClassName = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length()-SuffixConstants.EXTENSION_CLASS.length()-1);
+					for (String annotationPath : this.annotationPaths) {
+						try {
+							if (this.annotationZipFile == null) {
+								this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(annotationPath, null);
+							}
+							reader = ExternalAnnotationDecorator.create(reader, annotationPath, qualifiedClassName, this.annotationZipFile);
+
+							if (reader.getExternalAnnotationStatus() == ExternalAnnotationStatus.TYPE_IS_ANNOTATED) {
+								break;
+							}
+						} catch (IOException e) {
+							// don't let error on annotations fail class reading
+						}
+					}
+				}
+				return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), reader.getModule());
+			}
+		} catch(ClassFormatException e) {
+			// treat as if class file is missing
+		} catch (IOException e) {
+			// treat as if class file is missing
+		}
+		return null;
+	}
+	@Override
+	public boolean hasAnnotationFileFor(String qualifiedTypeName) {
+		return false; // TODO: Revisit 
+	}
+	public char[][][] findTypeNames(final String qualifiedPackageName, final IModule mod) {
+		if (!isPackage(qualifiedPackageName))
+			return null; // most common case
+		final char[] packageArray = qualifiedPackageName.toCharArray();
+		final ArrayList answers = new ArrayList();
+	
+		try {
+			JRTUtil.walkModuleImage(this.file, new JRTUtil.JrtFileVisitor<java.nio.file.Path>() {
+
+				@Override
+				public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path modPath, BasicFileAttributes attrs) throws IOException {
+					if (qualifiedPackageName.startsWith(dir.toString())) {
+						return FileVisitResult.CONTINUE;	
+					}
+					return FileVisitResult.SKIP_SUBTREE;
+				}
+
+				@Override
+				public FileVisitResult visitFile(java.nio.file.Path dir, java.nio.file.Path modPath, BasicFileAttributes attrs) throws IOException {
+					if (!dir.getParent().toString().equals(qualifiedPackageName)) {
+						return FileVisitResult.CONTINUE;
+					}
+					String fileName = dir.getName(dir.getNameCount() - 1).toString();
+					// The path already excludes the folders and all the '/', hence the -1 for last index of '/'
+					addTypeName(answers, fileName, -1, packageArray);
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitModule(java.nio.file.Path modPath) throws IOException {
+					if (mod == ModuleEnvironment.UNNAMED_MODULE)
+						return FileVisitResult.CONTINUE;
+					if (!CharOperation.equals(mod.name(), modPath.toString().toCharArray())) {
+						return FileVisitResult.SKIP_SUBTREE;
+					}
+					return FileVisitResult.CONTINUE;
+				}
+
+			}, JRTUtil.NOTIFY_ALL);
+		} catch (IOException e) {
+			// Ignore and move on
+		}
+		
+		int size = answers.size();
+		if (size != 0) {
+			char[][][] result = new char[size][][];
+			answers.toArray(result);
+			return result;
+		}
+		return null;
+	}
+
+	protected void addTypeName(final ArrayList answers, String fileName, int last, char[] packageName) {
+		int indexOfDot = fileName.lastIndexOf('.');
+		if (indexOfDot != -1) {
+			String typeName = fileName.substring(last + 1, indexOfDot);
+			answers.add(
+				CharOperation.arrayConcat(
+					CharOperation.splitOn('/', packageName),
+					typeName.toCharArray()));
+		}
+	}
+	public void initialize() throws IOException {
+		loadModules();
+	}
+//	public void acceptModule(IModuleDeclaration mod) {
+//		if (this.isJrt) 
+//			return;
+//		this.module = mod;
+//	}
+	public void loadModules() {
+		Set<IModule> cache = ModulesCache.get(this.file);
+
+		if (cache == null) {
+			try {
+				org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(this.file,
+						new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+
+					@Override
+					public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs)
+							throws IOException {
+						return FileVisitResult.CONTINUE;
+					}
+
+					@Override
+					public FileVisitResult visitFile(Path f, Path mod, BasicFileAttributes attrs)
+							throws IOException {
+						return FileVisitResult.CONTINUE;
+					}
+
+					@Override
+					public FileVisitResult visitModule(Path mod) throws IOException {
+						try {
+							ClasspathJrt.this.acceptModule(JRTUtil.getClassfileContent(ClasspathJrt.this.file, IModuleEnvironment.MODULE_INFO_CLASS, mod.toString()));
+						} catch (ClassFormatException e) {
+							e.printStackTrace();
+						}
+						return FileVisitResult.SKIP_SUBTREE;
+					}
+				}, JRTUtil.NOTIFY_MODULES);
+			} catch (IOException e) {
+				// TODO: BETA_JAVA9 Should report better
+			}
+		}
+	}
+	void acceptModule(ClassFileReader reader) {
+		if (reader != null) {
+			IModule moduleDecl = reader.getModuleDeclaration();
+			if (moduleDecl != null) {
+				Set<IModule> cache = ModulesCache.get(this.file);
+				if (cache == null) {
+					ModulesCache.put(new String(moduleDecl.name()), cache = new HashSet<IModule>());
+				}
+				cache.add(reader.getModuleDeclaration());
+			}
+		}
+		
+	}
+	void acceptModule(byte[] content) {
+		if (content == null) 
+			return;
+		ClassFileReader reader = null;
+		try {
+			reader = new ClassFileReader(content, IModuleEnvironment.MODULE_INFO_CLASS.toCharArray(), null);
+		} catch (ClassFormatException e) {
+			e.printStackTrace();
+		}
+		if (reader != null) {
+			acceptModule(reader);
+		}
+	}
+//	protected void addToPackageCache(String fileName, boolean endsWithSep) {
+//		int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/');
+//		while (last > 0) {
+//			// extract the package name
+//			String packageName = fileName.substring(0, last);
+//			if (this.packageCache.contains(packageName))
+//				return;
+//			this.packageCache.add(packageName);
+//			last = packageName.lastIndexOf('/');
+//		}
+//	}
+//	public synchronized boolean isPackage(String qualifiedPackageName) {
+//		if (this.packageCache != null)
+//			return this.packageCache.contains(qualifiedPackageName);
+//
+//		this.packageCache = new HashSet<>(41);
+//		this.packageCache.add(Util.EMPTY_STRING);
+//		
+//			try {
+//				JRTUtil.walkModuleImage(this.file, new JRTUtil.JrtFileVisitor<java.nio.file.Path>() {
+//
+//					@Override
+//					public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+//						addToPackageCache(dir.toString(), true);
+//						return FileVisitResult.CONTINUE;
+//					}
+//
+//					@Override
+//					public FileVisitResult visitFile(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+//						return FileVisitResult.CONTINUE;
+//					}
+//
+//					@Override
+//					public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException {
+//						return FileVisitResult.CONTINUE;
+//					}
+//
+//				}, JRTUtil.NOTIFY_PACKAGES);
+//			} catch (IOException e) {
+//				// Ignore and move on
+//			}
+//		return this.packageCache.contains(qualifiedPackageName);
+//	}
+	public void reset() {
+		if (this.closeZipFileAtEnd) {
+			if (this.annotationZipFile != null) {
+				try {
+					this.annotationZipFile.close();
+				} catch(IOException e) {
+					// ignore
+				}
+				this.annotationZipFile = null;
+			}
+		}
+		if (this.annotationPaths != null) {
+			//this.packageCache = null;
+			this.annotationPaths = null;
+		}
+	}
+	public String toString() {
+		return "Classpath for JRT System " + this.file.getPath(); //$NON-NLS-1$
+	}
+	public char[] normalizedPath() {
+		if (this.normalizedPath == null) {
+			String path2 = this.getPath();
+			char[] rawName = path2.toCharArray();
+			if (File.separatorChar == '\\') {
+				CharOperation.replace(rawName, '\\', '/');
+			}
+			this.normalizedPath = CharOperation.subarray(rawName, 0, CharOperation.lastIndexOf('.', rawName));
+		}
+		return this.normalizedPath;
+	}
+	public String getPath() {
+		if (this.path == null) {
+			try {
+				this.path = this.file.getCanonicalPath();
+			} catch (IOException e) {
+				// in case of error, simply return the absolute path
+				this.path = this.file.getAbsolutePath();
+			}
+		}
+		return this.path;
+	}
+	public int getMode() {
+		return BINARY;
+	}
+
+	public IModule getModule(char[] moduleName) {
+		Set<IModule> modules = ModulesCache.get(new String(moduleName));
+		if (modules != null) {
+			for (IModule mod : modules) {
+				if (CharOperation.equals(mod.name(), moduleName))
+						return mod;
+			}
+		}
+		return null;
+	}
+	@Override
+	public IMultiModuleTypeLookup typeLookup() {
+		return this::findClass;
+	}
+	@Override
+	public IMultiModulePackageLookup packageLookup() {
+		return this::isPackage;
+	}
+	@Override
+	public boolean servesModule(char[] mod) {
+		return ModulesCache.containsKey(new String(mod));
+	}
+
+
+	@Override
+	public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+		// 
+		return new IModuleEnvironment() {
+			
+			@Override
+			public ITypeLookup typeLookup() {
+				//
+				return servesModule(mod.name()) ? typeLookupForModule(mod.name()) : ITypeLookup.Dummy;
+			}
+			
+			@Override
+			public IPackageLookup packageLookup() {
+				//
+				return servesModule(mod.name()) ? pkgLookupForModule(mod.name()) : IPackageLookup.Dummy;
+			}
+		};
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironment() {
+		//
+		return this;
+	}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
index f0c5c07..e381857 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -15,6 +19,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IModule;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 public abstract class ClasspathLocation implements FileSystem.Classpath,
@@ -26,6 +31,8 @@
 	String path;
 	char[] normalizedPath;
 	public AccessRuleSet accessRuleSet;
+	IModule module;
+	protected boolean isAutoModule;
 
 	public String destinationPath;
 		// destination path for compilation units that are reached through this
@@ -100,4 +107,16 @@
 	public String getPath() {
 		return this.path;
 	}
+	public String getDestinationPath() {
+		return this.destinationPath;
+	}
+	
+	public void acceptModule(IModule mod) {
+		this.module = mod;
+		this.isAutoModule = mod.isAutomatic();
+	}
+	@Override
+	public boolean isAutomaticModule() {
+		return this.isAutoModule;
+	}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java
index fc94aa1..9430866 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathSourceJar.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2010 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -45,12 +49,14 @@
 					if (stream != null)
 						stream.close();
 				}
+				CompilationUnit compilationUnit = new CompilationUnit(
+					contents,
+					qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java,
+					this.encoding,
+					this.destinationPath);
+				compilationUnit.module = this.module == null ? null : this.module.name();
 				return new NameEnvironmentAnswer(
-					new CompilationUnit(
-						contents,
-						qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + SUFFIX_STRING_java,
-						this.encoding,
-						this.destinationPath),
+					compilationUnit,
 					fetchAccessRestriction(qualifiedBinaryFileName));
 			} catch (IOException e) {
 				// treat as if source file is missing
@@ -58,9 +64,7 @@
 		}
 		return null;
 	}
-	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
-		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
-	}
+
 	public int getMode() {
 		return SOURCE;
 	}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
index 64d3d89..04bc341 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -24,6 +28,7 @@
 	public char[] mainTypeName;
 	String encoding;
 	public String destinationPath;
+	public char[] module;
 		// a specific destination path for this compilation unit; coding is
 		// aligned with Main.destinationPath:
 		// == null: unspecified, use whatever value is set by the enclosing
@@ -38,11 +43,13 @@
 }
 public CompilationUnit(char[] contents, String fileName, String encoding,
 		String destinationPath) {
-	this(contents, fileName, encoding, destinationPath, false);
+	this(contents, fileName, encoding, destinationPath, false, null);
 }
 public CompilationUnit(char[] contents, String fileName, String encoding,
-		String destinationPath, boolean ignoreOptionalProblems) {
+		String destinationPath, boolean ignoreOptionalProblems, String modName) {
 	this.contents = contents;
+	if (modName != null)
+		this.module = modName.toCharArray();
 	char[] fileNameCharArray = fileName.toCharArray();
 	switch(File.separatorChar) {
 		case '/' :
@@ -98,4 +105,8 @@
 public String toString() {
 	return "CompilationUnit[" + new String(this.fileName) + "]";  //$NON-NLS-2$ //$NON-NLS-1$
 }
+@Override
+public char[] module() {
+	return this.module;
+}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
index f707fc0..efefe89 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -12,18 +16,26 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.List;
 
-@SuppressWarnings({"rawtypes", "unchecked"})
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+
 public class FileFinder {
 
+/**
+ * Although the file finder is meant to be generic for any file name patters,
+ * at the moment it is used only for *.java files. This method handles the 
+ * module-info.java in a special way by always placing it as the first element
+ * of the resulting array.
+ */
 public static String[] find(File f, String pattern) {
-	ArrayList files = new ArrayList();
+	List<String> files = new ArrayList<>();
 	find0(f, pattern, files);
 	String[] result = new String[files.size()];
 	files.toArray(result);
 	return result;
 }
-private static void find0(File f, String pattern, ArrayList collector) {
+private static void find0(File f, String pattern, List<String> collector) {
 	if (f.isDirectory()) {
 		String[] files = f.list();
 		if (files == null) return;
@@ -32,8 +44,15 @@
 			if (current.isDirectory()) {
 				find0(current, pattern, collector);
 			} else {
-				if (current.getName().toUpperCase().endsWith(pattern)) {
-					collector.add(current.getAbsolutePath());
+				String name = current.getName().toLowerCase();
+				if (name.endsWith(pattern)) {
+					// NOTE: This handles only the lower case name. Check with the spec about
+					// Naming of the module descriptor before making this code code insensitive.
+					if (name.endsWith(IModuleEnvironment.MODULE_INFO_JAVA)) {
+						collector.add(0, current.getAbsolutePath());
+					} else {
+						collector.add(current.getAbsolutePath());
+					}
 				}
 			}
 		}
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 bc3e10d..695a309 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -15,29 +19,45 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 @SuppressWarnings({ "rawtypes", "unchecked" })
-public class FileSystem implements INameEnvironment, SuffixConstants {
-	public interface Classpath {
-		char[][][] findTypeNames(String qualifiedPackageName);
-		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
-		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly);
-		boolean isPackage(String qualifiedPackageName);
+public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants {
+	/**
+	 * A <code>Classpath<code>, even though an IModuleLocation, can represent a plain
+	 * classpath location too. The FileSystem tells the Classpath whether to behave as a module or regular class
+	 * path via {@link Classpath#acceptModule(IModule)}.
+	 *
+	 * Sub types of classpath are responsible for appropriate behavior based on this.
+	 */
+	public interface Classpath extends IModulePathEntry {
+		char[][][] findTypeNames(String qualifiedPackageName, IModule module);
+		public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
+		public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly);
 		/**
 		 * Return a list of the jar file names defined in the Class-Path section
 		 * of the jar file manifest if any, null else. Only ClasspathJar (and
@@ -79,6 +99,13 @@
 		 * @param qualifiedTypeName type name in qualified /-separated notation.
 		 */
 		boolean hasAnnotationFileFor(String qualifiedTypeName);
+		/**
+		 * Accepts to represent a module location with the given module description.
+		 *
+		 * @param module
+		 */
+		public void acceptModule(IModule module);
+		public String getDestinationPath();
 	}
 	public interface ClasspathSectionProblemReporter {
 		void invalidClasspathSection(String jarFilePath);
@@ -113,14 +140,19 @@
 	}
 
 	protected Classpath[] classpaths;
+	// Used only in single-module mode when the module descriptor is
+	// provided via command lin.
+	protected IModule module;
 	Set knownFileNames;
 	protected boolean annotationsFromClasspath; // should annotation files be read from the classpath (vs. explicit separate path)?
+	private static HashMap<File, Classpath> JRT_CLASSPATH_CACHE = null;
 
 /*
 	classPathNames is a collection is Strings representing the full path of each class path
 	initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
 */
 public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding) {
+//	this.ms = new ModuleSystem(this);
 	final int classpathSize = classpathNames.length;
 	this.classpaths = new Classpath[classpathSize];
 	int counter = 0;
@@ -139,6 +171,7 @@
 	initializeKnownFileNames(initialFileNames);
 }
 protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annotationsFromClasspath) {
+//	this.ms = new ModuleSystem(this);
 	final int length = paths.length;
 	int counter = 0;
 	this.classpaths = new FileSystem.Classpath[length];
@@ -147,7 +180,8 @@
 		try {
 			classpath.initialize();
 			this.classpaths[counter++] = classpath;
-		} catch(IOException exception) {
+		} catch(IOException | IllegalArgumentException exception) {
+			// JRE 9 could throw an IAE if the linked JAR paths have invalid chars, such as ":"
 			// ignore
 		}
 	}
@@ -164,6 +198,9 @@
 public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map options) {
 	return getClasspath(classpathName, encoding, false, accessRuleSet, null, options);
 }
+public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map options) {
+	return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null);
+}
 public static Classpath getClasspath(String classpathName, String encoding,
 		boolean isSourceOnly, AccessRuleSet accessRuleSet,
 		String destinationPath, Map options) {
@@ -180,7 +217,8 @@
 						convertPathSeparators(destinationPath), options);
 		}
 	} else {
-		if (Util.isPotentialZipArchive(classpathName)) {
+		int format = Util.archiveFormat(classpathName);
+		if (format == Util.ZIP_FILE) {
 			if (isSourceOnly) {
 				// source only mode
 				result = new ClasspathSourceJar(file, true, accessRuleSet,
@@ -190,9 +228,29 @@
 						convertPathSeparators(destinationPath));
 			} else if (destinationPath == null) {
 				// class file only mode
-				result = new ClasspathJar(file, true, accessRuleSet, null);
+				if (classpathName.endsWith(JRTUtil.JRT_FS_JAR)) {
+					if (JRT_CLASSPATH_CACHE == null) {
+						JRT_CLASSPATH_CACHE = new HashMap<>();
+					} else {
+						result = JRT_CLASSPATH_CACHE.get(file);
+					}
+					if (result == null) {
+						result = new ClasspathJrt(file, true, accessRuleSet, null);
+						try {
+							result.initialize();
+						} catch (IOException e) {
+							// Broken entry, but let clients have it anyway.
+						}
+						JRT_CLASSPATH_CACHE.put(file, result);
+					}
+				} else {
+					result = new ClasspathJar(file, true, accessRuleSet, null);
+				}
 			}
+		} else if (format == Util.JMOD_FILE) {
+			// TODO BETA_JAVA9: we need new type of classpath to handle Jmod files in batch compiler.
 		}
+
 	}
 	return result;
 }
@@ -263,8 +321,11 @@
 		? path.replace('\\', '/')
 		 : path.replace('/', '\\');
 }
-private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly){
-	NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, asBinaryOnly);
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly) {
+	return findClass(qualifiedTypeName, typeName, asBinaryOnly, IModuleContext.UNNAMED_MODULE_CONTEXT);
+}
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, IModuleContext moduleContext) {
+	NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, asBinaryOnly, moduleContext);
 	if (this.annotationsFromClasspath && answer != null && answer.getBinaryType() instanceof ClassFileReader) {
 		for (int i = 0, length = this.classpaths.length; i < length; i++) {
 			Classpath classpathEntry = this.classpaths[i];
@@ -295,50 +356,6 @@
 	}
 	return answer;
 }
-private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly){
-	if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation
-
-	String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
-	String qualifiedPackageName =
-		qualifiedTypeName.length() == typeName.length
-			? Util.EMPTY_STRING
-			: qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
-	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
-	NameEnvironmentAnswer suggestedAnswer = null;
-	if (qualifiedPackageName == qp2) {
-		for (int i = 0, length = this.classpaths.length; i < length; i++) {
-			NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
-			if (answer != null) {
-				if (!answer.ignoreIfBetter()) {
-					if (answer.isBetter(suggestedAnswer))
-						return answer;
-				} else if (answer.isBetter(suggestedAnswer))
-					// remember suggestion and keep looking
-					suggestedAnswer = answer;
-			}
-		}
-	} else {
-		String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
-		for (int i = 0, length = this.classpaths.length; i < length; i++) {
-			Classpath p = this.classpaths[i];
-			NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
-				? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly)
-				: p.findClass(typeName, qp2, qb2, asBinaryOnly);
-			if (answer != null) {
-				if (!answer.ignoreIfBetter()) {
-					if (answer.isBetter(suggestedAnswer))
-						return answer;
-				} else if (answer.isBetter(suggestedAnswer))
-					// remember suggestion and keep looking
-					suggestedAnswer = answer;
-			}
-		}
-	}
-	if (suggestedAnswer != null)
-		// no better answer was found
-		return suggestedAnswer;
-	return null;
-}
 public NameEnvironmentAnswer findType(char[][] compoundName) {
 	if (compoundName != null)
 		return findClass(
@@ -347,47 +364,13 @@
 			false);
 	return null;
 }
-public char[][][] findTypeNames(char[][] packageName) {
-	char[][][] result = null;
-	if (packageName != null) {
-		String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
-		String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
-		if (qualifiedPackageName == qualifiedPackageName2) {
-			for (int i = 0, length = this.classpaths.length; i < length; i++) {
-				char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName);
-				if (answers != null) {
-					// concat with previous answers
-					if (result == null) {
-						result = answers;
-					} else {
-						int resultLength = result.length;
-						int answersLength = answers.length;
-						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
-						System.arraycopy(answers, 0, result, resultLength, answersLength);
-					}
-				}
-			}
-		} else {
-			for (int i = 0, length = this.classpaths.length; i < length; i++) {
-				Classpath p = this.classpaths[i];
-				char[][][] answers = (p instanceof ClasspathJar)
-					? p.findTypeNames(qualifiedPackageName)
-					: p.findTypeNames(qualifiedPackageName2);
-				if (answers != null) {
-					// concat with previous answers
-					if (result == null) {
-						result = answers;
-					} else {
-						int resultLength = result.length;
-						int answersLength = answers.length;
-						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
-						System.arraycopy(answers, 0, result, resultLength, answersLength);
-					}
-				}
-			}
-		}
-	}
-	return result;
+public NameEnvironmentAnswer findType(char[][] compoundName, IModuleContext moduleContext) {
+	if (compoundName != null)
+		return findClass(
+			new String(CharOperation.concatWith(compoundName, '/')),
+			compoundName[compoundName.length - 1],
+			false, moduleContext);
+	return null;
 }
 public NameEnvironmentAnswer findType(char[][] compoundName, boolean asBinaryOnly) {
 	if (compoundName != null)
@@ -405,20 +388,148 @@
 			false);
 	return null;
 }
-public boolean isPackage(char[][] compoundName, char[] packageName) {
-	String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
-	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
-	if (qualifiedPackageName == qp2) {
-		for (int i = 0, length = this.classpaths.length; i < length; i++)
-			if (this.classpaths[i].isPackage(qualifiedPackageName))
-				return true;
-	} else {
-		for (int i = 0, length = this.classpaths.length; i < length; i++) {
-			Classpath p = this.classpaths[i];
-			if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2))
-				return true;
+public char[][][] findTypeNames(char[][] packageName, IModule[] modules) {
+	char[][][] result = null;
+	if (packageName != null) {
+		String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
+		String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+		if (qualifiedPackageName == qualifiedPackageName2) {
+			for (int i = 0, length = this.classpaths.length; i < length; i++) {
+				for (IModule mod : modules) {
+					if (!CharOperation.equals(mod.name(), ModuleEnvironment.UNNAMED) && !this.classpaths[i].servesModule(mod.name())) continue;
+					char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName, mod);
+					if (answers != null) {
+						// concat with previous answers
+						if (result == null) {
+							result = answers;
+						} else {
+							int resultLength = result.length;
+							int answersLength = answers.length;
+							System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
+							System.arraycopy(answers, 0, result, resultLength, answersLength);
+						}
+					}
+				}
+			}
+		} else {
+			for (int i = 0, length = this.classpaths.length; i < length; i++) {
+				Classpath p = this.classpaths[i];
+				for (IModule mod : modules) {
+					if (!CharOperation.equals(mod.name(), ModuleEnvironment.UNNAMED) && !p.servesModule(mod.name())) continue;
+					char[][][] answers = (p instanceof ClasspathJar)
+							? p.findTypeNames(qualifiedPackageName, mod)
+							: p.findTypeNames(qualifiedPackageName2, mod);
+						if (answers != null) {
+							// concat with previous answers
+							if (result == null) {
+								result = answers;
+							} else {
+								int resultLength = result.length;
+								int answersLength = answers.length;
+								System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
+								System.arraycopy(answers, 0, result, resultLength, answersLength);
+							}
+						}
+				}
+			}
 		}
 	}
-	return false;
+	return result;
+}
+
+public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext moduleLookupContext) {
+	if (typeName == null)
+		return null;
+	String qualifiedTypeName = new String(CharOperation.concatWith(packageName, typeName, '/'));
+	NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, false, moduleLookupContext);
+	if (this.annotationsFromClasspath && answer != null && answer.getBinaryType() instanceof ClassFileReader) {
+		for (int i = 0, length = this.classpaths.length; i < length; i++) {
+			Classpath classpathEntry = this.classpaths[i];
+			if (classpathEntry.hasAnnotationFileFor(qualifiedTypeName)) {
+				@SuppressWarnings("resource")
+				ZipFile zip = classpathEntry instanceof ClasspathJar ? ((ClasspathJar) classpathEntry).zipFile : null;
+				try {
+					if (zip == null) {
+						zip = ExternalAnnotationDecorator.getAnnotationZipFile(classpathEntry.getPath(), null);
+					}
+					answer.setBinaryType(ExternalAnnotationDecorator.create(answer.getBinaryType(), classpathEntry.getPath(), 
+							qualifiedTypeName, zip));
+					break;
+				} catch (IOException e) {
+					// ignore broken entry, keep searching
+				}
+			}
+		}
+	}
+	return answer;
+	
+}
+public boolean isPackage(char[][] compoundName, char[] packageName) {
+	return isPackage(compoundName, packageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+}
+public boolean isPackage(char[][] compoundName, char[] packageName, IModuleContext moduleContext) {
+	String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
+	if (moduleContext == IModuleContext.UNNAMED_MODULE_CONTEXT) {
+		return Stream.of(this.classpaths).map(p -> p.getLookupEnvironment().packageLookup()).filter(l -> l.isPackage(qualifiedPackageName)).findAny().isPresent();
+	} else {
+		return moduleContext.getEnvironment().map(e -> e.packageLookup()).filter(l -> l.isPackage(qualifiedPackageName)).findAny().isPresent();
+	}
+}
+void addReads(String source, String target) {
+	IModule src = getModule(source.toCharArray());
+	if (src != null) {
+		src.addReads(target.toCharArray());
+	}
+}
+void setAddonExports(Map<String, IPackageExport[]> exports) {
+	exports.entrySet().forEach((entry) -> {
+		IModule src = getModule(entry.getKey().toCharArray());
+		if (src != null) {
+			src.addExports(entry.getValue());
+		}
+	});
+}
+@Override
+public IModule getModule(char[] name) {
+	if (name == null)
+		return null;
+	if (this.module != null && CharOperation.equals(name, this.module.name())) {
+		return this.module;
+	}
+	return Stream.of(this.classpaths).map(cp -> cp.getModule(name)).filter(m -> m != null).findAny().orElse(null);
+	
+}
+public IModuleEnvironment getModuleEnvironmentFor(char[] moduleName) {
+	return (IModuleEnvironment) Stream.of(this.classpaths).filter(cp -> cp.getModule(moduleName) != null).findAny().orElse(null);
+}
+private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, IModuleContext moduleContext) {
+	if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation
+
+	String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
+	String qualifiedPackageName =
+		qualifiedTypeName.length() == typeName.length
+			? Util.EMPTY_STRING
+			: qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
+
+	if (IModuleContext.UNNAMED_MODULE_CONTEXT == moduleContext) {
+		return Stream.of(this.classpaths)
+				.map(p -> p.getLookupEnvironment().typeLookup())
+				.reduce(ITypeLookup::chain)
+				.map(t -> t.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly)).orElse(null);
+	}
+	return moduleContext.getEnvironment().map(env -> env.typeLookup())
+				.reduce(ITypeLookup::chain)
+				.map(lookup -> lookup.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly))
+				.orElse(null);
+}
+@Override
+public IModule[] getAllAutomaticModules() {
+	Set<IModule> set = new HashSet<>();
+	for (int i = 0, l = this.classpaths.length; i < l; i++) {
+		if (this.classpaths[i].isAutomaticModule()) {
+			set.add(this.classpaths[i].getModule());
+		}
+	}
+	return set.toArray(new IModule[set.size()]);
 }
 }
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 0f4bb64..b1f3e2b 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Tom Tromey - Contribution for bug 125961
@@ -48,6 +52,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
@@ -74,16 +79,23 @@
 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.AccessRule;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.CompilerStats;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -509,10 +521,14 @@
 						File f = new File(classpath);
 						String id = null;
 						if (f.isFile()) {
-							if (Util.isPotentialZipArchive(classpath)) {
-								id = Logger.CLASSPATH_JAR;
-							} else {
-								id = Logger.CLASSPATH_FILE;
+							int kind = Util.archiveFormat(classpath);
+							switch (kind) {
+								case Util.ZIP_FILE:
+									id = Logger.CLASSPATH_JAR;
+									break;
+								default:
+									id = Logger.CLASSPATH_FILE;
+									break;
 							}
 						} else if (f.isDirectory()) {
 							id = Logger.CLASSPATH_FOLDER;
@@ -1337,10 +1353,15 @@
 	/* Bundle containing messages */
 	public ResourceBundle bundle;
 	protected FileSystem.Classpath[] checkedClasspaths;
+	// For single module mode
+	protected IModule module;
 	// paths to external annotations:
 	protected List<String> annotationPaths;
 	protected boolean annotationsFromClasspath;
 
+	private List<String> addonExports = Collections.EMPTY_LIST;
+	private List<String> addonReads = Collections.EMPTY_LIST;
+
 	public Locale compilerLocale;
 	public CompilerOptions compilerOptions; // read-only
 	public CompilationProgress progress;
@@ -1359,6 +1380,7 @@
 	public String[] encodings;
 	public int exportedClassFilesCounter;
 	public String[] filenames;
+	public String[] modNames;
 	public String[] classNames;
 	// overrides of destinationPath on a directory argument basis
 	public int globalErrorsCount;
@@ -1433,7 +1455,7 @@
 public static File[][] getLibrariesFiles(File[] files) {
 	FilenameFilter filter = new FilenameFilter() {
 		public boolean accept(File dir, String name) {
-			return Util.isPotentialZipArchive(name);
+			return Util.archiveFormat(name) > -1;
 		}
 	};
 	final int filesLength = files.length;
@@ -1589,8 +1611,9 @@
 	if (NONE.equals(destPath)) {
 		destPath = NONE; // keep == comparison valid
 	}
+	
 	if (rejectDestinationPathOnJars && destPath != null &&
-			Util.isPotentialZipArchive(currentClasspathName)) {
+			Util.archiveFormat(currentClasspathName) > -1) {
 		throw new IllegalArgumentException(
 			this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$
 						currentClasspathName));
@@ -1706,6 +1729,8 @@
 			return ClassFileConstants.JDK1_7 >= minimalSupportedVersion;
 		case ClassFileConstants.MAJOR_VERSION_1_8: // 1.8
 			return ClassFileConstants.JDK1_8 >= minimalSupportedVersion;
+		case ClassFileConstants.MAJOR_VERSION_9: // 9
+			return ClassFileConstants.JDK9 >= minimalSupportedVersion;
 	}
 	// unknown version
 	return false;
@@ -1805,10 +1830,17 @@
 	final int INSIDE_CLASS_NAMES = 20;
 	final int INSIDE_WARNINGS_PROPERTIES = 21;
 	final int INSIDE_ANNOTATIONPATH_start = 22;
+	final int INSIDE_MODULEPATH_start = 23;
+	final int INSIDE_MODULESOURCEPATH_start = 24;
+	final int INSIDE_ADD_EXPORTS = 25;
+	final int INSIDE_ADD_READS = 26;
+	final int INSIDE_SYSTEM = 27;
 
 	final int DEFAULT = 0;
 	ArrayList bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
 	String sourcepathClasspathArg = null;
+	String modulepathArg = null;
+	String moduleSourcepathArg = null;
 	ArrayList sourcepathClasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
 	ArrayList classpaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
 	ArrayList extdirsClasspaths = null;
@@ -1834,6 +1866,7 @@
 	String customDestinationPath = null;
 	String currentSourceDirectory = null;
 	String currentArg = Util.EMPTY_STRING;
+	String moduleName = null;
 	
 	Set specifiedEncodings = null;
 
@@ -1965,9 +1998,21 @@
 				}
 
 				if (currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) {
+					if (moduleName == null) {
+						// If the module-info.java was supplied via command line, that will be the
+						// de facto module for the other source files supplied via command line.
+						// TODO: This needs revisit in case a source file specified in command line is
+						// part of a --module-source-path
+						IModule mod = extractModuleDesc(currentArg, getNewParser());
+						if (mod != null) {
+							moduleName = new String(mod.name());
+							this.module = mod;
+						}
+					}
 					if (this.filenames == null) {
 						this.filenames = new String[argCount - index];
 						this.encodings = new String[argCount - index];
+						this.modNames = new String[argCount - index];
 						this.destinationPaths = new String[argCount - index];
 					} else if (filesCount == this.filenames.length) {
 						int length = this.filenames.length;
@@ -1989,8 +2034,15 @@
 							(this.destinationPaths = new String[length + argCount - index]),
 							0,
 							length);
+						System.arraycopy(
+								this.modNames,
+								0,
+								(this.modNames = new String[length + argCount - index]),
+								0,
+								length);
 					}
 					this.filenames[filesCount] = currentArg;
+					this.modNames[filesCount] = moduleName;
 					this.encodings[filesCount++] = customEncoding;
 					// destination path cannot be specified upon an individual file
 					customEncoding = null;
@@ -2086,6 +2138,16 @@
 					mode = DEFAULT;
 					continue;
 				}
+				if (currentArg.equals("-1.9") || currentArg.equals("-9") || currentArg.equals("-9.0")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					if (didSpecifyCompliance) {
+						throw new IllegalArgumentException(
+							this.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+					}
+					didSpecifyCompliance = true;
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
+					mode = DEFAULT;
+					continue;
+				}
 				if (currentArg.equals("-d")) { //$NON-NLS-1$
 					if (this.destinationPath != null) {
 						StringBuffer errorMessage = new StringBuffer();
@@ -2119,6 +2181,26 @@
 					mode = INSIDE_BOOTCLASSPATH_start;
 					continue;
 				}
+				if (currentArg.equals("--system")) { //$NON-NLS-1$
+					mode = INSIDE_SYSTEM;
+					continue;
+				}
+				if (currentArg.equals("--module-path") || currentArg.equals("-p")) { //$NON-NLS-1$ //$NON-NLS-2$
+					mode = INSIDE_MODULEPATH_start;
+					continue;
+				}
+				if (currentArg.equals("--module-source-path")) { //$NON-NLS-1$
+					mode = INSIDE_MODULESOURCEPATH_start;
+					continue;
+				}
+				if (currentArg.equals("--add-exports")) { //$NON-NLS-1$
+					mode = INSIDE_ADD_EXPORTS;
+					continue;
+				}
+				if (currentArg.equals("--add-reads")) { //$NON-NLS-1$
+					mode = INSIDE_ADD_READS;
+					continue;
+				}
 				if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
 					if (sourcepathClasspathArg != null) {
 						StringBuffer errorMessage = new StringBuffer();
@@ -2580,6 +2662,8 @@
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
 				} else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
+				} else if (currentArg.equals("1.9") || currentArg.equals("9") || currentArg.equals("9.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
 				}
 				else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14);
@@ -2636,6 +2720,8 @@
 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
 				} else if (currentArg.equals("1.8") || currentArg.equals("8") || currentArg.equals("8.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
 					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
+				} else if (currentArg.equals("1.9") || currentArg.equals("9") || currentArg.equals("9.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
 				} else {
 					throw new IllegalArgumentException(this.bind("configure.source", currentArg)); //$NON-NLS-1$
 				}
@@ -2674,6 +2760,38 @@
 				setDestinationPath(currentArg.equals(NONE) ? NONE : currentArg);
 				mode = DEFAULT;
 				continue;
+			case INSIDE_SYSTEM:
+				mode = DEFAULT;
+				this.javaHomeCache = new File(currentArg);
+				this.javaHomeChecked = true;
+				continue;
+			case INSIDE_MODULEPATH_start:
+				mode = DEFAULT;
+				String[] modulepaths = new String[1];
+				index += processPaths(newCommandLineArgs, index, currentArg, modulepaths);
+				modulepathArg = modulepaths[0];
+				continue;
+			case INSIDE_MODULESOURCEPATH_start:
+				mode = DEFAULT;
+				String[] moduleSourcepaths = new String[1];
+				index += processPaths(newCommandLineArgs, index, currentArg, moduleSourcepaths);
+				moduleSourcepathArg = moduleSourcepaths[0];
+				continue;
+			case INSIDE_ADD_EXPORTS:
+				mode = DEFAULT;
+				// TODO: better to validate the option before processing it further?
+				if (this.addonExports == Collections.EMPTY_LIST) {
+					this.addonExports = new ArrayList<>();
+				}
+				this.addonExports.add(currentArg);
+				continue;
+			case INSIDE_ADD_READS:
+				mode = DEFAULT;
+				if (this.addonReads == Collections.EMPTY_LIST) {
+					this.addonReads = new ArrayList<>();
+				}
+				this.addonReads.add(currentArg);
+				continue;
 			case INSIDE_CLASSPATH_start:
 				mode = DEFAULT;
 				index += processPaths(newCommandLineArgs, index, currentArg, classpaths);
@@ -2790,7 +2908,7 @@
 			throw new IllegalArgumentException(
 				this.bind("configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$
 		}
-		String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_JAVA);
+		String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_java);
 		if (NONE.equals(customDestinationPath)) {
 			customDestinationPath = NONE; // ensure == comparison
 		}
@@ -2815,10 +2933,17 @@
 				(this.destinationPaths = new String[length + filesCount]),
 				0,
 				filesCount);
+			System.arraycopy(
+					this.modNames,
+					0,
+					(this.modNames = new String[length + filesCount]),
+					0,
+					filesCount);
 			System.arraycopy(result, 0, this.filenames, filesCount, length);
 			for (int i = 0; i < length; i++) {
 				this.encodings[filesCount + i] = customEncoding;
 				this.destinationPaths[filesCount + i] = customDestinationPath;
+				this.modNames[filesCount + i] = moduleName;
 			}
 			filesCount += length;
 			customEncoding = null;
@@ -2829,6 +2954,7 @@
 			filesCount = this.filenames.length;
 			this.encodings = new String[filesCount];
 			this.destinationPaths = new String[filesCount];
+			this.modNames = new String[filesCount];
 			for (int i = 0; i < filesCount; i++) {
 				this.encodings[i] = customEncoding;
 				this.destinationPaths[i] = customDestinationPath;
@@ -2875,8 +3001,9 @@
 			CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
 			CompilerOptions.PRIVATE);
 	}
-
-	if (printUsageRequired || (filesCount == 0 && classCount == 0)) {
+	// We don't add the source files from --module-source-path yet to the final list. So,
+	// don't report it if that's the case.
+	if (printUsageRequired || (filesCount == 0 && classCount == 0 && moduleSourcepathArg == null)) {
 		if (usageSection ==  null) {
 			printUsage(); // default
 		} else {
@@ -2934,6 +3061,8 @@
 			sourcepathClasspathArg,
 			sourcepathClasspaths,
 			classpaths,
+			modulepathArg,
+			moduleSourcepathArg,
 			extdirsClasspaths,
 			endorsedDirClasspaths,
 			customEncoding);
@@ -2951,6 +3080,32 @@
 		this.pendingErrors = null;
 	}
 }
+private Parser getNewParser() {
+	return new Parser(new ProblemReporter(getHandlingPolicy(), 
+			new CompilerOptions(this.options), getProblemFactory()), false);
+}
+private IModule extractModuleDesc(String fileName, Parser parser) {
+	IModule mod = null;
+	if (fileName.toLowerCase().endsWith(IModuleEnvironment.MODULE_INFO_JAVA)) {
+		
+		ICompilationUnit cu = new CompilationUnit(null, fileName, null);
+		CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10);
+		CompilationUnitDeclaration unit = parser.parse(cu, compilationResult);
+		if (unit.isModuleInfo() && unit.moduleDeclaration != null) {
+			mod = new BasicModule(unit.moduleDeclaration, null);
+		}
+	} else if (fileName.toLowerCase().endsWith(IModuleEnvironment.MODULE_INFO_CLASS)) {
+		try {
+			ClassFileReader reader = ClassFileReader.read(fileName); // Check the absolute path?
+			mod = reader.getModuleDeclaration();
+		} catch (ClassFormatException | IOException e) {
+			e.printStackTrace();
+			throw new IllegalArgumentException(
+					this.bind("configure.invalidModuleDescriptor", fileName)); //$NON-NLS-1$
+		}
+	}
+	return mod;
+}
 
 private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) {
 	StringTokenizer tokenizer = new StringTokenizer(folders, File.pathSeparator);
@@ -3134,7 +3289,8 @@
 			fileName = this.filenames[i];
 		}
 		units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i],
-				shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()));
+				shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()), 
+				this.modNames[i]);
 	}
 	return units;
 }
@@ -3170,8 +3326,11 @@
 }
 
 public FileSystem getLibraryAccess() {
-	return new FileSystem(this.checkedClasspaths, this.filenames, 
+	FileSystem nameEnvironment = new FileSystem(this.checkedClasspaths, this.filenames, 
 					this.annotationsFromClasspath && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis)));
+	nameEnvironment.module = this.module;
+	processAddonModuleOptions(nameEnvironment);
+	return nameEnvironment;
 }
 
 /*
@@ -3199,7 +3358,7 @@
 	} else {
 		bootclasspaths = new ArrayList(DEFAULT_SIZE_CLASSPATH);
 		try {
-			Util.collectRunningVMBootclasspath(bootclasspaths);
+			Util.collectVMBootclasspath(bootclasspaths, this.javaHomeCache);
 		} catch(IllegalStateException e) {
 			this.logger.logWrongJDK();
 			this.proceed = false;
@@ -3208,7 +3367,149 @@
 	}
 	return bootclasspaths;
 }
+private void processAddonModuleOptions(FileSystem env) {
+	Map<String, IPackageExport[]> exports = new HashMap<>();
+	for (String option : this.addonExports) {
+		IModule mod = ModuleFinder.extractAddonExport(option);
+		if (mod != null) {
+			String modName = new String(mod.name());
+			IPackageExport export = mod.exports()[0];
+			IPackageExport[] existing = exports.get(modName);
+			if (existing == null) {
+				existing = new IPackageExport[1];
+				existing[0] = export;
+				exports.put(modName, existing);
+			} else {
+				for (IPackageExport iPackageExport : existing) {
+					if (CharOperation.equals(iPackageExport.name(), export.name())) {
+						throw new IllegalArgumentException(this.bind("configure.duplicateExport")); //$NON-NLS-1$
+					}
+				}
+				IPackageExport[] updated = new IPackageExport[existing.length + 1];
+				System.arraycopy(existing, 0, updated, 0, existing.length);
+				updated[existing.length] = export;
+				exports.put(modName, updated);
+			}
+		} else {
+			throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-exports " + option)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+	env.setAddonExports(exports);
+	for (String option : this.addonReads) {
+		String[] result = ModuleFinder.extractAddonRead(option);
+		if (result != null && result.length == 2) {
+			env.addReads(result[0], result[1]);
+		} else {
+			throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-reads " + option)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+}
+protected ArrayList handleModulepath(String arg) {
+	ArrayList<String> modulePaths = processModulePathEntries(arg);
+	final int classpathsSize;
+	if ((modulePaths != null && modulePaths.size() > 0)
+		&& ((classpathsSize = modulePaths.size()) != 0)) {
+		String[] paths = new String[classpathsSize];
+		modulePaths.toArray(paths);
+		modulePaths.clear();
+		for (int i = 0; i < paths.length; i++) {
+			File dir = new File(paths[i]);
+			if (dir.isDirectory()) {
+			modulePaths =
+					(ArrayList) ModuleFinder.findModules(dir, null, getNewParser(), this.options, true);
+			}
+		}
+	}
+	// TODO: What about chained jars from MANIFEST.MF? Check with spec
+	return modulePaths;
+}
+protected ArrayList handleModuleSourcepath(String arg) {
+	ArrayList<String> modulePaths = processModulePathEntries(arg);
+	final int classpathsSize;
+	if ((modulePaths != null)
+		&& ((classpathsSize = modulePaths.size()) != 0)) {
 
+		if (this.destinationPath == null) {
+			addPendingErrors(this.bind("configure.missingDestinationPath"));//$NON-NLS-1$
+		}
+		String[] paths = new String[modulePaths.size()];
+		modulePaths.toArray(paths);
+		// We reuse the same List to store <Classpath>, which earlier contained <String>
+		modulePaths.clear();
+		for (int i = 0; i < classpathsSize; i++) {
+			processPathEntries(DEFAULT_SIZE_CLASSPATH, modulePaths, paths[i],
+					null, false, true);
+		}
+//		Parser parser = getNewParser();
+		for (int i = 0; i < paths.length; i++) {
+			File dir = new File(paths[i]);
+			if (dir.isDirectory()) {
+				// 1. Create FileSystem.Classpath for each module
+				// 2. Iterator each module in case of directory for source files and add to this.fileNames
+
+				modulePaths =
+						(ArrayList) ModuleFinder.findModules(dir, this.destinationPath, getNewParser(), this.options, false);
+				for (Object obj : modulePaths) {
+					Classpath classpath = (Classpath) obj;
+					File modLocation = new File(classpath.getPath());
+					String[] result = FileFinder.find(modLocation, SuffixConstants.SUFFIX_STRING_java);
+					String destPath = classpath.getDestinationPath();
+					IModule mod = classpath.getModule();
+					String moduleName = mod == null ? null : new String(mod.name());
+
+					// Add them to this.filenames
+					if (this.filenames != null) {
+						int filesCount = this.filenames.length;
+						// some source files were specified explicitly
+						int length = result.length;
+						System.arraycopy(
+							this.filenames,
+							0,
+							(this.filenames = new String[length + filesCount]),
+							0,
+							filesCount);
+						System.arraycopy(
+							this.encodings,
+							0,
+							(this.encodings = new String[length + filesCount]),
+							0,
+							filesCount);
+						System.arraycopy(
+							this.destinationPaths,
+							0,
+							(this.destinationPaths = new String[length + filesCount]),
+							0,
+							filesCount);
+						System.arraycopy(
+								this.modNames,
+								0,
+								(this.modNames = new String[length + filesCount]),
+								0,
+								filesCount);
+						System.arraycopy(result, 0, this.filenames, filesCount, length);
+						for (int j = 0; j < length; j++) {
+							this.modNames[filesCount + j] = moduleName;
+							this.destinationPaths[filesCount + j] = destPath;
+						}
+						filesCount += length;
+					} else {
+						this.filenames = result;
+						int filesCount = this.filenames.length;
+						this.encodings = new String[filesCount];
+						this.destinationPaths = new String[filesCount];
+						this.modNames = new String[filesCount];
+						for (int j = 0; j < filesCount; j++) {
+							this.destinationPaths[j] = destPath;
+							this.modNames[j] = moduleName;
+						}
+					}
+				}
+			}
+		}
+		
+	}
+	return modulePaths;
+}
 /*
  * External API
  */
@@ -4334,7 +4635,7 @@
 		} else {
 			compoundName = new char[][] { currentName.toCharArray() };
 		}
-		ReferenceBinding type = environment.getType(compoundName);
+		ReferenceBinding type = environment.getType(compoundName, null);
 		if (type != null && type.isValidBinding()) {
 			if (type.isBinaryBinding()) {
 				referenceBindings[i] = type;
@@ -4346,6 +4647,16 @@
 	}
 	return referenceBindings;
 }
+private ArrayList<String> processModulePathEntries(String arg) {
+	ArrayList<String> paths = new ArrayList<>();
+	if (arg == null)
+		return paths;
+	StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator, false);
+	while (tokenizer.hasMoreTokens()) {
+		paths.add(tokenizer.nextToken());
+	}
+	return paths;
+}
 /*
  * External API
  */
@@ -4686,18 +4997,36 @@
 		String sourcepathClasspathArg,
 		ArrayList sourcepathClasspaths,
 		ArrayList classpaths,
+		String modulePath,
+		String moduleSourcepath,
 		ArrayList extdirsClasspaths,
 		ArrayList endorsedDirClasspaths,
 		String customEncoding) {
 
+	Object version = this.options.get(CompilerOptions.OPTION_Compliance);
+	if (CompilerOptions.VERSION_9.equals(version)) {
+		if (bootclasspaths != null && bootclasspaths.size() > 0)
+			throw new IllegalArgumentException(
+				this.bind("configure.unsupportedOption", "-bootclasspath")); //$NON-NLS-1$ //$NON-NLS-2$
+		if (extdirsClasspaths != null && extdirsClasspaths.size() > 0)
+			throw new IllegalArgumentException(
+				this.bind("configure.unsupportedOption", "-extdirs")); //$NON-NLS-1$ //$NON-NLS-2$
+		if (endorsedDirClasspaths != null && endorsedDirClasspaths.size() > 0)
+			throw new IllegalArgumentException(
+				this.bind("configure.unsupportedOption", "-endorseddirs")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
 	// process bootclasspath, classpath and sourcepaths
  	bootclasspaths = handleBootclasspath(bootclasspaths, customEncoding);
 
 	classpaths = handleClasspath(classpaths, customEncoding);
 
+	List modulePaths = handleModulepath(modulePath);
+
+	List moduleSourcepaths = handleModuleSourcepath(moduleSourcepath);
+
 	if (sourcepathClasspathArg != null) {
 		processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepathClasspaths,
-			sourcepathClasspathArg, customEncoding, true, false);
+			sourcepathClasspathArg, null, true, false);
 	}
 
 	/*
@@ -4722,6 +5051,8 @@
 	bootclasspaths.addAll(extdirsClasspaths);
 	bootclasspaths.addAll(sourcepathClasspaths);
 	bootclasspaths.addAll(classpaths);
+	bootclasspaths.addAll(modulePaths);
+	bootclasspaths.addAll(moduleSourcepaths);
 	classpaths = bootclasspaths;
 	classpaths = FileSystem.ClasspathNormalizer.normalize(classpaths);
 	this.checkedClasspaths = new FileSystem.Classpath[classpaths.size()];
@@ -4826,6 +5157,26 @@
 				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
 				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
 			}
+		} else if (CompilerOptions.VERSION_9.equals(version)) {
+			if (this.didSpecifySource) {
+				Object source = this.options.get(CompilerOptions.OPTION_Source);
+				if (CompilerOptions.VERSION_1_3.equals(source)
+						|| CompilerOptions.VERSION_1_4.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+				} else if (CompilerOptions.VERSION_1_5.equals(source)
+						|| CompilerOptions.VERSION_1_6.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
+				} else if (CompilerOptions.VERSION_1_7.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
+				} else if (CompilerOptions.VERSION_1_8.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
+				} else if (CompilerOptions.VERSION_9.equals(source)) {
+					if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
+				}
+			} else {
+				this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
+				if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
+			}
 		}
 	} else if (this.didSpecifySource) {
 		Object version = this.options.get(CompilerOptions.OPTION_Source);
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java
new file mode 100644
index 0000000..02e2460
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.PackageExportImpl;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ModuleFinder {
+
+	protected static List<FileSystem.Classpath> findModules(File f, String destinationPath, Parser parser, Map<String, String> options, boolean isModulepath) {
+		List<FileSystem.Classpath> collector = new ArrayList<>();
+		if (f.isDirectory()) {
+			File[] files = f.listFiles();
+			if (files == null) 
+				return Collections.EMPTY_LIST;
+			for (final File file : files) {
+				FileSystem.Classpath modulePath = FileSystem.getClasspath(
+						file.getAbsolutePath(),
+						null,
+						!isModulepath,
+						null,
+						destinationPath == null ? null : (destinationPath + File.separator + file.getName()), 
+						options);
+				if (modulePath != null) {
+					collector.add(modulePath);
+					IModule module = null;
+					if (file.isDirectory()) {
+						String[] list = file.list(new FilenameFilter() {
+							@Override
+							public boolean accept(File dir, String name) {
+								if (dir == file && (name.equalsIgnoreCase(IModuleEnvironment.MODULE_INFO_CLASS)
+										|| name.equalsIgnoreCase(IModuleEnvironment.MODULE_INFO_JAVA))) {
+									return true;
+								}
+								return false;
+							}
+						});
+						if (list.length > 0) {
+							String fileName = list[0];
+							switch (fileName) {
+								case IModuleEnvironment.MODULE_INFO_CLASS:
+									module = ModuleFinder.extractModuleFromClass(new File(file, fileName), modulePath);
+									break;
+								case IModuleEnvironment.MODULE_INFO_JAVA:
+									module = ModuleFinder.extractModuleFromSource(new File(file, fileName), parser, modulePath);
+									break;
+							}
+						}
+					} else if (isJar(file)) {
+						module = extractModuleFromJar(file, modulePath);
+					}
+					if (isModulepath && module == null) {
+						 // The name includes the file's extension, but it shouldn't matter.
+						module = new ModuleEnvironment.AutoModule(getFileName(file).toCharArray());
+					}
+					if (module != null)
+						modulePath.acceptModule(module);
+				}
+			}
+		}
+		return collector;
+	}
+	private static String getFileName(File file) {
+		String name = file.getName();
+		int index = name.lastIndexOf('.');
+		if (index == -1)
+			return name;
+		return name.substring(0, index);
+	}
+	/**
+	 * Extracts the single reads clause from the given
+	 * command line option (--add-reads). The result is a String[] with two
+	 * element, first being the source module and second being the target module.
+	 * The expected format is: 
+	 *  --add-reads <source-module>=<target-module>
+	 * @param option
+	 * @return a String[] with source and target module of the "reads" clause. 
+	 */
+	protected static String[] extractAddonRead(String option) {
+		StringTokenizer tokenizer = new StringTokenizer(option, "="); //$NON-NLS-1$
+		String source = null;
+		String target = null;
+		if (tokenizer.hasMoreTokens()) {
+			source = tokenizer.nextToken();
+		} else {
+			// Handle error
+			return null;
+		}
+		if (tokenizer.hasMoreTokens()) {
+			target = tokenizer.nextToken();
+		} else {
+			// Handle error
+			return null;
+		}
+ 		return new String[]{source, target};
+	}
+	/**
+	 * Parses the --add-exports command line option and returns the package export definitions
+	 * in the form of an IModule. Note the IModule returned only holds this specific exports-to
+	 * clause and can't by itself be used as a module description.
+	 *
+	 * The expected format is:
+	 *   --add-exports <source-module>/<package>=<target-module>(,<target-module>)*
+	 * @param option
+	 * @return a dummy module object with package exports
+	 */
+	protected static IModule extractAddonExport(String option) {
+		StringTokenizer tokenizer = new StringTokenizer(option, "/"); //$NON-NLS-1$
+		String source = null;
+		String pack = null;
+		List<String> targets = new ArrayList<>();
+		if (tokenizer.hasMoreTokens()) {
+			source = tokenizer.nextToken("/"); //$NON-NLS-1$
+		} else {
+			// Handle error
+			return null;
+		}
+		if (tokenizer.hasMoreTokens()) {
+			pack = tokenizer.nextToken("/="); //$NON-NLS-1$
+		} else {
+			// Handle error
+			return null;
+		}
+		while (tokenizer.hasMoreTokens()) {
+			targets.add(tokenizer.nextToken("=,")); //$NON-NLS-1$
+		}
+		PackageExportImpl export = new PackageExportImpl();
+		export.pack = pack.toCharArray();
+		export.exportedTo = new char[targets.size()][];
+		for(int i = 0; i < export.exportedTo.length; i++) {
+			export.exportedTo[i] = targets.get(i).toCharArray();
+		}
+		BasicModule module = new BasicModule(source.toCharArray(), false);
+		module.exports = new IModule.IPackageExport[]{export};
+		return module;
+	}
+
+	private static boolean isJar(File file) {
+		int format = Util.archiveFormat(file.getAbsolutePath());
+		return format >= Util.ZIP_FILE;
+	}
+	private static IModule extractModuleFromJar(File file, Classpath pathEntry) {
+		ZipFile zipFile = null;
+		try {
+			zipFile = new ZipFile(file);
+			ClassFileReader reader = ClassFileReader.read(zipFile, IModuleEnvironment.MODULE_INFO_CLASS);
+			IModule module = getModule(reader);
+			if (module != null) {
+				return reader.getModuleDeclaration();
+			}
+			return null;
+		} catch (ClassFormatException | IOException e) {
+			e.printStackTrace();
+		} finally {
+			if (zipFile != null) {
+				try {
+					zipFile.close();
+				} catch (IOException e) {
+					// Nothing much to do here
+				}
+			}
+		}
+		return null;
+	}
+	private static IModule extractModuleFromClass(File classfilePath, Classpath pathEntry) {
+		ClassFileReader reader;
+		try {
+			reader = ClassFileReader.read(classfilePath);
+			IModule module =  getModule(reader);
+			if (module != null) {
+				return reader.getModuleDeclaration();
+			}
+			return null;
+		} catch (ClassFormatException | IOException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+	private static IModule getModule(ClassFileReader classfile) {
+		if (classfile != null) {
+			return classfile.getModuleDeclaration();
+		}
+		return null;
+	}
+	private static IModule extractModuleFromSource(File file, Parser parser, Classpath pathEntry) {
+		ICompilationUnit cu = new CompilationUnit(null, file.getAbsolutePath(), null);
+		CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10);
+		CompilationUnitDeclaration unit = parser.parse(cu, compilationResult);
+		if (unit.isModuleInfo() && unit.moduleDeclaration != null) {
+			return new BasicModule(unit.moduleDeclaration, pathEntry);
+		}
+		return null;
+	}
+}
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 6c6f265..190a0fa 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
@@ -5,6 +5,10 @@
 # which accompanies this distribution, and is available at
 # http://www.eclipse.org/legal/epl-v10.html
 #
+# This is an implementation of an early-draft specification developed under the Java
+# Community Process (JCP) and is made available for testing and evaluation purposes
+# only. The code is not compatible with any specification of the JCP.
+#
 # Contributors:
 #     IBM Corporation - initial API and implementation
 #		Benjamin Muskalla - Contribution for bug 239066
@@ -26,7 +30,7 @@
 #Format: compiler.name = word1 word2 word3
 compiler.name = Eclipse Compiler for Java(TM)
 #Format: compiler.version = (The place holders will be automatically filled. Do not remove or alter it)
-compiler.version = bundle_qualifier, bundle_version
+compiler.version = bundle_qualifier, bundle_version BETA_JAVA9
 compiler.copyright = Copyright IBM Corp 2000, 2015. All rights reserved.
 
 ### progress
@@ -60,8 +64,15 @@
 configure.duplicateCompliance = duplicate compliance setting specification: {0}
 configure.duplicateSource = duplicate source compliance setting specification: {0}
 configure.duplicateTarget = duplicate target compliance setting specification: {0}
-configure.source = source level should be comprised in between ''1.3'' and ''1.8'' (or ''5'', ''5.0'', ..., ''8'' or ''8.0''): {0}
+configure.source = source level should be comprised in between ''1.3'' and ''1.9'' (or ''5'', ''5.0'', ..., ''9'' or ''9.0''): {0}
+configure.invalidSystem = invalid location for system libraries
+configure.unsupportedOption = option {0} not supported at compliance level 9 and above
 configure.duplicateOutputPath = duplicate output path specification: {0}
+configure.duplicateModulePath = duplicate module path specification: {0}
+configure.duplicateModuleSourcepath = duplicate source module path specification: {0}
+configure.invalidModuleDescriptor = cannot open the module descriptor from {0}
+configure.invalidModuleOption = incorrectly formatted option: {0}
+configure.duplicateExport = can specify a package in a module only once with --add-export
 configure.duplicateBootClasspath = duplicate bootclasspath specification: {0}
 configure.duplicateExtDirs = duplicate extdirs specification: {0}
 configure.duplicateSourcepath = duplicate sourcepath specification: {0}
@@ -69,7 +80,7 @@
 configure.invalidWarningConfiguration = invalid warning configuration: ''{0}''
 configure.invalidWarning = invalid warning token: ''{0}''. Ignoring warning and compiling
 configure.invalidWarningOption = invalid warning option: ''{0}''. Must specify a warning token
-configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.8'' (or ''5'', ''5.0'', ..., ''8'' or ''8.0'') or cldc1.1: {0}
+configure.targetJDK = target level should be comprised in between ''1.1'' and ''1.9'' (or ''5'', ''5.0'', ..., ''9'' or ''9.0'') or cldc1.1: {0}
 configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required
 configure.incompatibleTargetForGenericSource = Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.5'' or better is required
 configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required
@@ -101,6 +112,7 @@
 configure.incorrectExtDirsEntry = incorrect ext dir entry; {0} must be a directory
 configure.incorrectEndorsedDirsEntry = incorrect endorsed dir entry; {0} must be a directory
 configure.duplicateEndorsedDirs = duplicate endorseddirs specification: {0}
+configure.missingDestinationPath = destination path must be provided with module source path
 configure.incorrectDestinationPathEntry = incorrect destination path entry: {0}
 configure.unexpectedBracket = unexpected bracket: {0}
 configure.unexpectedDestinationPathEntry = unexpected destination path entry in {0} option
@@ -192,6 +204,14 @@
 \                       If multiple default encodings are specified, the last\n\
 \                       one will be used.\n\
 \ \n\
+\ Module compilation options:\n\
+\   These options are meaningful only in Java 9 environment or later.\n\
+\    --module-source-path <directories separated by {0}>\n\
+\                       specify where to find source files for multiple modules\n\
+\    -p --module-path <directories separated by {0}>\n\
+\                       specify where to find application modules\n\
+\    --system <jdk>      Override location of system modules\
+\ \n\
 \ Compliance options:\n\
 \    -1.3               use 1.3 compliance (-source 1.3 -target 1.1)\n\
 \    -1.4             + use 1.4 compliance (-source 1.3 -target 1.2)\n\
@@ -199,8 +219,9 @@
 \    -1.6 -6 -6.0       use 1.6 compliance (-source 1.6 -target 1.6)\n\
 \    -1.7 -7 -7.0       use 1.7 compliance (-source 1.7 -target 1.7)\n\
 \    -1.8 -8 -8.0       use 1.8 compliance (-source 1.8 -target 1.8)\n\
-\    -source <version>  set source level: 1.3 to 1.8 (or 5, 5.0, etc)\n\
-\    -target <version>  set classfile target: 1.1 to 1.8 (or 5, 5.0, etc)\n\
+\    -1.9 -9 -9.0       use 1.9 compliance (-source 1.9 -target 1.9)\n\
+\    -source <version>  set source level: 1.3 to 1.9 (or 6, 6.0, etc)\n\
+\    -target <version>  set classfile target: 1.1 to 1.9 (or 6, 6.0, etc)\n\
 \                       cldc1.1 can also be used to generate the StackMap\n\
 \                       attribute\n\
 \ \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 835639b..41081ef 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     Timo Kinnunen - Contributions for bug 377373 - [subwords] known limitations with JDT 3.8
  *     							Bug 420953 - [subwords] Constructors that don't match prefix not found
@@ -17,9 +21,13 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.stream.Stream;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.CompletionContext;
@@ -28,8 +36,10 @@
 import org.eclipse.jdt.core.CompletionRequestor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IAccessRule;
+import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.ITypeRoot;
 import org.eclipse.jdt.core.JavaCore;
@@ -40,6 +50,12 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeDetector;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionNodeFound;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnAnnotationOfType;
@@ -61,6 +77,8 @@
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadocTypeParamReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword3;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleDeclaration;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeywordModuleInfo;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnLocalName;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMarkerAnnotationName;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMemberAccess;
@@ -69,8 +87,15 @@
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMessageSendName;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodName;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodReturnType;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleDeclaration;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnModuleReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnPackageVisibilityReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsQualifiedTypeReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesImplementationsSingleTypeReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesQualifiedTypeReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnProvidesInterfacesSingleTypeReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedAllocationExpression;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedNameReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnQualifiedTypeReference;
@@ -78,6 +103,8 @@
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleNameReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleTypeReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionOnStringLiteral;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesQualifiedTypeReference;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnUsesSingleTypeReference;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionParser;
 import org.eclipse.jdt.internal.codeassist.complete.CompletionScanner;
 import org.eclipse.jdt.internal.codeassist.complete.InvalidCursorLocation;
@@ -121,16 +148,21 @@
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.OperatorExpression;
 import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
 import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.SuperReference;
@@ -142,11 +174,13 @@
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
 import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
 import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
@@ -198,12 +232,16 @@
 import org.eclipse.jdt.internal.core.BinaryTypeConverter;
 import org.eclipse.jdt.internal.core.INamingRequestor;
 import org.eclipse.jdt.internal.core.InternalNamingConventions;
+import org.eclipse.jdt.internal.core.JavaElementRequestor;
 import org.eclipse.jdt.internal.core.JavaModelManager;
-import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.ModuleSourcePathManager;
 import org.eclipse.jdt.internal.core.SourceMethod;
 import org.eclipse.jdt.internal.core.SourceMethodElementInfo;
 import org.eclipse.jdt.internal.core.SourceType;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
 import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
 import org.eclipse.jdt.internal.core.search.matching.IndexBasedJavaSearchEnvironment;
 import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -677,7 +715,12 @@
 	ProblemReporter problemReporter;
 	private INameEnvironment noCacheNameEnvironment;
 	char[] source;
+	ModuleDeclaration moduleDeclaration;
 	char[] completionToken;
+	IModuleContext moduleContext = () -> {
+		return Stream.of((JavaProject)this.javaProject);
+	};
+
 	char[] qualifiedCompletionToken;
 	boolean resolvingImports = false;
 	boolean resolvingStaticImports = false;
@@ -692,6 +735,7 @@
 	String complianceLevel;
 	SimpleSetOfCharArray validPackageNames = new SimpleSetOfCharArray(10);
 	SimpleSetOfCharArray invalidPackageNames = new SimpleSetOfCharArray(1);
+	HashtableOfObject knownModules = new HashtableOfObject(10);
 	HashtableOfObject knownPkgs = new HashtableOfObject(10);
 	HashtableOfObject knownTypes = new HashtableOfObject(10);
 	
@@ -1244,6 +1288,42 @@
 			this.acceptedTypes = null; // reset
 		}
 	}
+	
+	/**
+	 * One result of the search consists of a new module.
+	 *
+	 * NOTE - All module names are presented in their readable form:
+	 *    Module names are in the form "a.b.c".
+	 *    The default module is represented by an empty array.
+	 */
+	public void acceptModule(char[] moduleName) {
+		if (this.knownModules.containsKey(moduleName)) return;
+		if (CharOperation.equals(moduleName, this.moduleDeclaration.moduleName)) return;
+		if (CharOperation.equals(moduleName, CharOperation.NO_CHAR)) return;
+		this.knownModules.put(moduleName, this);
+		char[] completion = moduleName;
+		int relevance = computeBaseRelevance();
+		relevance += computeRelevanceForResolution();
+		relevance += computeRelevanceForInterestingProposal();
+		relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, moduleName);
+		relevance += computeRelevanceForQualification(true);
+		relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+		this.noProposal = false;
+		if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
+			InternalCompletionProposal proposal = createProposal(CompletionProposal.MODULE_REF, this.actualCompletionPosition);
+			proposal.setModuleName(moduleName);
+			proposal.setDeclarationSignature(moduleName);
+			proposal.setCompletion(completion);
+			proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+			proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
+			proposal.setRelevance(relevance);
+			this.requestor.accept(proposal);
+			if(DEBUG) {
+				this.printDebug(proposal);
+			}
+		}
+		
+	}
 
 	/**
 	 * One result of the search consists of a new package.
@@ -1847,6 +1927,14 @@
 			completionOnMethodReturnType(astNode, scope);
 		} else if (astNode instanceof CompletionOnSingleNameReference) {
 			completionOnSingleNameReference(astNode, astNodeParent, scope, insideTypeAnnotation);
+		} else if (astNode instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
+			completionOnProvidesInterfacesQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+		} else if (astNode instanceof CompletionOnProvidesInterfacesSingleTypeReference) {
+			completionOnProvidesInterfacesSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+		} else if (astNode instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
+			completionOnProvidesImplementationsQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+		} else if (astNode instanceof CompletionOnProvidesImplementationsSingleTypeReference) {
+			completionOnProvidesImplementationsSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
 		} else if (astNode instanceof CompletionOnSingleTypeReference) {
 			completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
 		} else if (astNode instanceof CompletionOnQualifiedNameReference) {
@@ -1954,6 +2042,97 @@
 					System.out.println(parsedUnit.toString());
 				}
 
+				if (parsedUnit.isModuleInfo()) {
+					this.moduleDeclaration = parsedUnit.moduleDeclaration;
+					if (this.moduleDeclaration == null) return;
+					if (this.moduleDeclaration instanceof CompletionOnModuleDeclaration) {
+						contextAccepted = true;
+						buildContext(parsedUnit.moduleDeclaration, null, parsedUnit, null, null);
+						//this.requestor.setIgnored(CompletionProposal.MODULE_DECLARATION, false); //TODO: Hack until ui fixes this issue.
+						if(!this.requestor.isIgnored(CompletionProposal.MODULE_DECLARATION)) {
+							findModuleName(parsedUnit);
+						}
+						debugPrintf(); 
+						return;
+					}
+					if (this.moduleDeclaration instanceof CompletionOnKeywordModuleDeclaration) {
+						contextAccepted = true;
+						processModuleKeywordCompletion(parsedUnit, this.moduleDeclaration, (CompletionOnKeyword) this.moduleDeclaration);
+						return;
+					}
+					if (this.moduleDeclaration.exports != null) {
+						contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.exports);
+						if (contextAccepted) return;
+					}
+					if (this.moduleDeclaration.opens != null) {
+						contextAccepted = completeOnPackageVisibilityStatements(contextAccepted, parsedUnit, this.moduleDeclaration.opens);
+						if (contextAccepted) return;
+					}
+					RequiresStatement[] moduleRefs = this.moduleDeclaration.requires;
+					if (moduleRefs != null) {
+						for (int i = 0, l = moduleRefs.length; i < l; ++i) {
+							ModuleReference reference = moduleRefs[i].module;
+							if (reference instanceof CompletionOnModuleReference) {
+								contextAccepted = true;
+								buildContext(reference, null, parsedUnit, null, null);
+								if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
+									findModules((CompletionOnModuleReference) reference, false /* targetted */);
+								}
+								debugPrintf();
+								return;
+							}
+						}
+					}
+					UsesStatement[] uses = this.moduleDeclaration.uses;
+					if (uses != null) {
+						for (int i = 0, l = uses.length; i < l; ++i) {
+							TypeReference usesReference = uses[i].serviceInterface;
+							if (usesReference instanceof CompletionOnUsesSingleTypeReference ||
+									usesReference instanceof CompletionOnUsesQualifiedTypeReference) {
+								this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
+								if ((this.unitScope = parsedUnit.scope) != null) {
+									contextAccepted = true;
+									buildContext(usesReference, null, parsedUnit, null, null);
+									findTypeReferences(usesReference, true);
+									debugPrintf();
+									return;
+								}
+							}
+						}
+					}
+					ProvidesStatement[] providesStmts = this.moduleDeclaration.services;
+					for (int i = 0, l = providesStmts != null ? providesStmts.length : 0; i < l; ++i) {
+						ProvidesStatement providesStmt = providesStmts[i];
+						TypeReference pInterface = providesStmt.serviceInterface;
+						if (pInterface instanceof CompletionOnProvidesInterfacesSingleTypeReference ||
+								pInterface instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
+							this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
+							if ((this.unitScope = parsedUnit.scope) != null) {
+								contextAccepted = true;
+								buildContext(pInterface, null, parsedUnit, null, null);
+								findTypeReferences(pInterface, true);
+								debugPrintf();
+								return;
+							}
+						}
+						TypeReference[] implementations = providesStmt.implementations;
+						for (int j = 0, k = implementations.length; j < k; ++j) {
+							TypeReference implementation = implementations[i];
+							
+							if (implementation instanceof CompletionOnProvidesImplementationsSingleTypeReference ||
+									implementation instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
+								this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
+								if ((this.unitScope = parsedUnit.scope) != null) {
+									contextAccepted = true;
+									buildContext(implementation, null, parsedUnit, null, null);
+									findImplementations(providesStmt, i/* stmtIndex */, j/* implIndex */);
+									debugPrintf();
+									return;
+								}
+							}
+						}
+					}
+				}
 				// scan the package & import statements first
 				if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
 					contextAccepted = true;
@@ -1961,12 +2140,7 @@
 					if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
 						findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
 					}
-					if(this.noProposal && this.problem != null) {
-						this.requestor.completionFailure(this.problem);
-						if(DEBUG) {
-							this.printDebug(this.problem);
-						}
-					}
+					debugPrintf();
 					return;
 				}
 
@@ -2016,12 +2190,7 @@
 									}
 								}
 
-								if(this.noProposal && this.problem != null) {
-									this.requestor.completionFailure(this.problem);
-									if(DEBUG) {
-										this.printDebug(this.problem);
-									}
-								}
+								debugPrintf();
 							}
 							return;
 						} else if(importReference instanceof CompletionOnKeyword) {
@@ -2032,12 +2201,7 @@
 								CompletionOnKeyword keyword = (CompletionOnKeyword)importReference;
 								findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null);
 							}
-							if(this.noProposal && this.problem != null) {
-								this.requestor.completionFailure(this.problem);
-								if(DEBUG) {
-									this.printDebug(this.problem);
-								}
-							}
+							debugPrintf();
 							return;
 						}
 					}
@@ -2145,6 +2309,68 @@
 		}
 	}
 
+	private boolean completeOnPackageVisibilityStatements(boolean contextAccepted,
+			CompilationUnitDeclaration parsedUnit, PackageVisibilityStatement[] pvsStmts) {
+		for (int i = 0, l = pvsStmts.length; i < l; ++i) {
+			PackageVisibilityStatement pvs = pvsStmts[i];
+			if (pvs instanceof CompletionOnKeywordModuleInfo) { // dummy pvs statement
+				contextAccepted = true;
+				processModuleKeywordCompletion(parsedUnit, pvs, (CompletionOnKeyword) pvs);
+				return contextAccepted;
+			}
+			if (pvs.pkgRef instanceof CompletionOnPackageVisibilityReference) {
+				contextAccepted = true;
+				buildContext(pvs, null, parsedUnit, null, null);
+				if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+					findPackages((CompletionOnPackageVisibilityReference) pvs.pkgRef);
+				}
+				debugPrintf();
+				return contextAccepted;
+			}
+			ModuleReference[] targets = pvs.targets;
+			if (targets == null) continue;
+			HashSet<String> skipSet = new HashSet<>();
+			for (int j = 0, lj = targets.length; j < lj; j++) {
+				ModuleReference target = targets[j];
+				if (target == null) break;
+				if (target instanceof CompletionOnModuleReference) {
+					buildContext(target, null, parsedUnit, null, null);
+					contextAccepted = true;
+					if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
+						findTargettedModules((CompletionOnModuleReference) target, skipSet);
+					}
+					debugPrintf();
+					return contextAccepted;
+				} else if (target instanceof CompletionOnKeyword) {
+					contextAccepted = true;
+					processModuleKeywordCompletion(parsedUnit, target, (CompletionOnKeyword) target);
+				} else {
+					if (target.moduleName != null || target.moduleName.equals(CharOperation.NO_CHAR))
+						skipSet.add(new String(target.moduleName));
+				}
+			}
+		}
+		return contextAccepted;
+	}
+
+	private void debugPrintf() {
+		if(this.noProposal && this.problem != null) {
+			this.requestor.completionFailure(this.problem);
+			if(DEBUG) {
+				this.printDebug(this.problem);
+			}
+		}
+	}
+
+	private void processModuleKeywordCompletion(CompilationUnitDeclaration parsedUnit, ASTNode node, CompletionOnKeyword keyword) {
+		buildContext(node, null, parsedUnit, null, null);
+		if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+			setSourceAndTokenRange(node.sourceStart, node.sourceEnd);
+			findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, parsedUnit.currentPackage != null);
+		}
+		debugPrintf();
+	}
+
 	public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
 		if(this.requestor != null){
 			this.requestor.beginReporting();
@@ -3391,6 +3617,16 @@
 		}
 	}
 	
+	private void completionOnProvidesInterfacesQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
+		// TODO: Filter the results wrt accessibility and add relevance to the results.
+		completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+	}
+
+	private void completionOnProvidesImplementationsQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
+		// TODO: Filter the results wrt accessibility and add relevance to the results.
+		completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+	}
+
 	private void completionOnSingleNameReference(ASTNode astNode, ASTNode astNodeParent, Scope scope,
 			boolean insideTypeAnnotation) {
 		CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode;
@@ -3524,6 +3760,15 @@
 		}
 	}
 
+	private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
+		// TODO : filter the results.
+		completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+	}
+	private void completionOnProvidesImplementationsSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
+		// TODO : filter the results.
+		completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+	}
+
 	private char[][] computeAlreadyDefinedName(
 			BlockScope scope,
 			InvocationSite invocationSite) {
@@ -10379,12 +10624,79 @@
 		}
 	}
 
-	private void findPackages(CompletionOnPackageReference packageStatement) {
+	private void findModuleName(CompilationUnitDeclaration parsedUnit) {
+		char[] fileName1 = parsedUnit.getFileName();
+		if (fileName1 == null || !CharOperation.endsWith(fileName1, MODULE_INFO_FILE_NAME)) return;
+		int lastFileSeparatorIndex = fileName1.length - (MODULE_INFO_FILE_NAME.length + 1);
+		if (lastFileSeparatorIndex  <= 0) return;
+		int prevFileSeparatorIndex = CharOperation.lastIndexOf(fileName1[lastFileSeparatorIndex], fileName1, 0, lastFileSeparatorIndex - 1);
+		prevFileSeparatorIndex = prevFileSeparatorIndex < 0 ? 0 : prevFileSeparatorIndex + 1;
+		char[] moduleName = CharOperation.subarray(fileName1, prevFileSeparatorIndex, lastFileSeparatorIndex);
+		if (moduleName == null || moduleName.length == 0) return;
+		this.completionToken = CharOperation.concatWith(this.moduleDeclaration.tokens, '.');
+		if (this.completionToken.length > 0 && !CharOperation.prefixEquals(this.completionToken, moduleName)) return;
 
+		InternalCompletionProposal proposal =  createProposal(CompletionProposal.MODULE_DECLARATION, this.actualCompletionPosition);
+		proposal.setName(moduleName);
+		proposal.setCompletion(moduleName);
+		proposal.setReplaceRange((this.startPosition < 0) ? 0 : this.startPosition - this.offset, this.endPosition - this.offset);
+		proposal.setTokenRange((this.tokenStart < 0) ? 0 : this.tokenStart - this.offset, this.tokenEnd - this.offset);
+		proposal.setRelevance(R_MODULE_DECLARATION);
+		this.requestor.accept(proposal);
+		if(DEBUG) {
+			this.printDebug(proposal);
+		}
+	}
+
+	private void findTargettedModules(char[] prefix, HashSet<String> skipSet) {
+		ModuleSourcePathManager mManager = JavaModelManager.getModulePathManager();
+		JavaElementRequestor javaElementRequestor = new JavaElementRequestor();
+		try {
+			mManager.seekModule(this.completionToken, true, javaElementRequestor);
+			IModuleDescription[] modules = javaElementRequestor.getModules();
+			for (IModuleDescription module : modules) {
+				String name = module.getElementName();
+				if (name == null || name.equals("") || skipSet.contains(name)) //$NON-NLS-1$
+					continue;
+				this.acceptModule(name.toCharArray());
+			}
+		} catch (JavaModelException e) {
+			// TODO ignore for now
+		}
+	}
+	private void findTargettedModules(CompletionOnModuleReference moduleReference, HashSet<String> skipSet) {
+		setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions);
+		findTargettedModules(CharOperation.toLowerCase(this.completionToken), skipSet);
+	}
+
+	private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions, boolean without) {
+		this.completionToken = without ? CharOperation.concatWith(tokens, '.') : CharOperation.concatWithAll(tokens, '.');
+		if (this.completionToken.length == 0)
+			this.completionToken = CharOperation.ALL_PREFIX;
+		setSourceRange(sourceStart, sourceEnd);
+		long completionPosition = sourcePositions[sourcePositions.length - 1];
+		setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
+	}
+	private void setCompletionToken(char[][] tokens, int sourceStart, int sourceEnd, long[] sourcePositions) {
+		setCompletionToken(tokens, sourceStart, sourceEnd, sourcePositions, true);
+	}
+	private void findModules(CompletionOnModuleReference moduleReference, boolean targetted) {
+		setCompletionToken(moduleReference.tokens, moduleReference.sourceStart, moduleReference.sourceEnd, moduleReference.sourcePositions);
+		findTargettedModules(moduleReference, new HashSet<>()); // empty skipSet passed
+		this.nameEnvironment.findModules(CharOperation.toLowerCase(this.completionToken), this, targetted ? this.javaProject : null);
+	}
+	private void findPackages(CompletionOnPackageVisibilityReference reference) {
+		setCompletionToken(reference.tokens, reference.sourceStart, reference.sourceEnd, reference.sourcePositions, false);
+		findPackagesInCurrentModule();
+	}
+
+	private void findPackagesInCurrentModule() {
+		this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, this.moduleContext);
+	}
+	private void findPackages(CompletionOnPackageReference packageStatement) {
 		this.completionToken = CharOperation.concatWithAll(packageStatement.tokens, '.');
 		if (this.completionToken.length == 0)
 			return;
-
 		setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
 		long completionPosition = packageStatement.sourcePositions[packageStatement.sourcePositions.length - 1];
 		setTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
@@ -10722,16 +11034,17 @@
 								hasMemberTypesInEnclosingScope(sourceType, scope)) ||
 								hasArrayTypeAsExpectedSuperTypes()) {
 					char[] typeName = sourceType.sourceName();
-					createTypeProposal(
-							sourceType,
-							typeName,
-							IAccessRule.K_ACCESSIBLE,
-							typeName,
-							relevance,
-							null,
-							null,
-							null,
-							false);
+					if (!sourceType.isModule())
+						createTypeProposal(
+								sourceType,
+								typeName,
+								IAccessRule.K_ACCESSIBLE,
+								typeName,
+								relevance,
+								null,
+								null,
+								null,
+								false);
 				}
 				
 				if (proposeConstructor) {
@@ -11299,6 +11612,7 @@
 	
 	private void findTypesFromStaticImports(char[] token, Scope scope, boolean proposeAllMemberTypes, ObjectVector typesFound) {
 		ImportBinding[] importBindings = scope.compilationUnitScope().imports;
+		if (importBindings == null) return;
 		for (int i = 0; i < importBindings.length; i++) {
 			ImportBinding importBinding = importBindings[i];
 			if(importBinding.isValidBinding() && importBinding.isStatic()) {
@@ -11538,6 +11852,138 @@
 		return null;
 	}
 
+	private void findTypeReferences(TypeReference reference, boolean findMembers) {
+		char[][] tokens = reference.getTypeName();
+
+		char[] typeName = CharOperation.concatWithAll(tokens, '.');
+
+		if (typeName.length == 0) {
+			this.completionToken = new char[] {'*'};
+		} else if (reference instanceof CompletionOnUsesQualifiedTypeReference ||
+				reference instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
+			CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference;
+			if (qReference.completionIdentifier != null) {
+				this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.');
+			}
+		} else {
+			 char[] lastToken = tokens[tokens.length - 1];
+			 this.completionToken = lastToken != null && lastToken.length == 0 ?
+					 CharOperation.concat(typeName, new char[]{'.'}) :lastToken;
+		}
+		setSourceRange(reference.sourceStart, reference.sourceEnd);
+		findTypesAndPackages(this.completionToken, this.unitScope, true, true, new ObjectVector());
+	}
+
+	private void findImplementations(ProvidesStatement providesStmt, int stmtIndex, int implIndex) {
+		TypeReference reference = providesStmt.implementations[implIndex];
+		char[][] tokens = reference.getTypeName();
+		char[] typeName = CharOperation.concatWithAll(tokens, '.');
+
+		if (typeName.length == 0) {
+			this.completionToken = CharOperation.ALL_PREFIX;
+		} else if (reference instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
+			CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference;
+			if (qReference.completionIdentifier != null) {
+				this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.');
+			}
+		} else {
+			 char[] lastToken = tokens[tokens.length - 1];
+			 this.completionToken = lastToken != null && lastToken.length == 0 ?
+					 CharOperation.concat(typeName, new char[]{'.'}) :lastToken;
+		}
+		setSourceRange(reference.sourceStart, reference.sourceEnd);
+		findImplementations(this.completionToken, this.unitScope, providesStmt, stmtIndex);
+	}
+
+	private void findImplementations(char[] token, Scope scope, ProvidesStatement providesStmt, int stmtIndex) {
+
+		TypeReference theInterface = providesStmt.serviceInterface;
+
+		if (token == null) return;
+		char[][] theInterfaceType = theInterface.getTypeName();
+		if (theInterfaceType == null) return;
+		SearchPattern pattern  = null;
+		NameEnvironmentAnswer answer =  this.nameEnvironment.findType(theInterfaceType);
+		if (answer != null ) {
+			if (answer.isSourceType()) {
+				IType typeHandle = ((SourceTypeElementInfo) answer.getSourceTypes()[0]).getHandle();
+				pattern = SearchPattern.createPattern(typeHandle, IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
+			} else if (answer.isBinaryType()) {
+				String typeName = new String(CharOperation.replaceOnCopy(answer.getBinaryType().getName(), '/', '.'));
+				pattern = SearchPattern.createPattern(typeName,
+						IJavaSearchConstants.CLASS_AND_INTERFACE,
+						IJavaSearchConstants.IMPLEMENTORS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
+			}
+		}
+		if (pattern == null) return;
+		IJavaSearchScope searchScope = BasicSearchEngine.createJavaSearchScope(new IJavaElement[] {this.javaProject});
+		class ImplSearchRequestor extends SearchRequestor {
+			String prefix;
+			List<String> filter;
+			public List<IType> types = new ArrayList<>();
+			public ImplSearchRequestor(char[] prefixToken, List<String> filter) {
+				this.prefix = (prefixToken == CharOperation.ALL_PREFIX) ? null : new String(prefixToken);
+				this.filter = filter;
+			}
+			@Override
+			public void acceptSearchMatch(SearchMatch match) throws CoreException {
+				checkCancel();
+				IJavaElement element = ((IJavaElement) match.getElement());
+				if (element.getElementType() == IJavaElement.TYPE) {
+					IType type = (IType) element;
+					if (this.prefix != null) {
+						String fullTypeName = type.getPackageFragment().getElementName();
+						if (fullTypeName != null) {
+							fullTypeName = fullTypeName.concat(".").concat(type.getElementName()); //$NON-NLS-1$
+						} else {
+							fullTypeName = type.getElementName();
+						}
+						if (!fullTypeName.startsWith(this.prefix) || this.filter.contains(fullTypeName)) return;
+					}
+					this.types.add(type);
+				}
+			}
+		}
+		try {
+			List<String> existingImpl = new ArrayList<>();
+			char[][] theInterfaceName = theInterface.getTypeName();
+			// filter out existing implementations of the same interfaces
+			for (int i = 0, l = this.moduleDeclaration.servicesCount; i < l; ++i) {
+				if (i == stmtIndex) continue;
+				ProvidesStatement prevProvides = this.moduleDeclaration.services[i];
+				if (!CharOperation.equals(theInterfaceName, prevProvides.serviceInterface.getTypeName())) continue;
+				TypeReference[] prevImpls = prevProvides.implementations;
+				for (TypeReference prevImpl : prevImpls) {
+					char[][] typeName = prevImpl.getTypeName();
+					if (typeName.equals(CharOperation.NO_CHAR_CHAR)) continue;
+					existingImpl.add(CharOperation.toString(typeName));
+				}
+			}
+			// use search infrastructure - faster than using model
+			ImplSearchRequestor searchRequestor = new ImplSearchRequestor(this.completionToken, existingImpl);
+			new SearchEngine(this.owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(this.owner, true/*add primary WCs*/)).search(
+					pattern,
+					new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()},
+					searchScope,
+					searchRequestor,
+					null
+					);
+			for (IType type : searchRequestor.types) {
+				String pkg = type.getPackageFragment().getElementName();
+				String name = type.getElementName();
+				this.acceptType(pkg.toCharArray(), name.toCharArray(), CharOperation.NO_CHAR_CHAR, type.getFlags(), null);
+				acceptTypes(scope);
+			}
+		} catch (CoreException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+			checkCancel();
+			findPackagesInCurrentModule();
+		}
+	}
+
 	private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) {
 		final TypeReference type = variable.type;
 		if(type != null &&
@@ -12229,6 +12675,11 @@
 			if(target != 0 && (target & TagBits.AnnotationForPackage) == 0) {
 				return false;
 			}
+		} else if (this.targetedElement == TagBits.AnnotationForModule) {
+			long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK;
+			if(target != 0 && (target & TagBits.AnnotationForModule) == 0) {
+				return false;
+			}
 		} else if ((this.targetedElement & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) {
 			if (scope.parent != null &&
 					scope.parent.parent != null &&
@@ -13032,6 +13483,7 @@
 		super.reset(false);
 		this.validPackageNames = new SimpleSetOfCharArray(10);
 		this.invalidPackageNames = new SimpleSetOfCharArray(1);
+		this.knownModules = new HashtableOfObject(10);
 		this.knownPkgs = new HashtableOfObject(10);
 		this.knownTypes = new HashtableOfObject(10);
 		if (this.noCacheNameEnvironment != null) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
index 23beccc..f87241b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
@@ -90,4 +90,6 @@
 	 *    The default package is represented by an empty array.
 	 */
 	public void acceptPackage(char[] packageName);
+	
+	public void acceptModule(char[] moduleName);
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
index cd0b4bb..1209112 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/ISelectionRequestor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -52,6 +56,20 @@
 		int end);
 
 	/**
+	 * Code assist notification of a module selection.
+	 *
+	 * @param moduleName name of the module
+	 * @param uniqueKey unique key of this module
+	 * @param start Start of the selection
+	 * @param end End of the selection
+	 */
+	void acceptModule(
+			char[] moduleName,
+			char[] uniqueKey,
+			int start,
+			int end);
+
+	/**
 	 * Code assist notification of a compilation error detected during selection.
 	 *  @param error CategorizedProblem
 	 *      Only problems which are categorized as errors are notified to the requestor,
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
index b2427c4..9c6fbe8 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Andreas Magnusson <andreas.ch.magnusson@gmail.com>- contribution for bug 151500
@@ -50,6 +54,7 @@
 
 	protected char[] declarationPackageName;
 	protected char[] declarationTypeName;
+	protected char[] moduleName;
 	protected char[] packageName;
 	protected char[] typeName;
 	protected char[][] parameterPackageNames;
@@ -377,6 +382,10 @@
 		return JavaModelManager.getJavaModelManager().getOpenableCacheSize() / 10;
 	}
 
+	protected char[] getModuleName() {
+		return this.moduleName;
+	}
+
 	protected char[] getPackageName() {
 		return this.packageName;
 	}
@@ -402,6 +411,10 @@
 		this.declarationTypeName = declarationTypeName;
 	}
 
+	protected void setModuleName(char[] moduleName) {
+		this.moduleName = moduleName;
+	}
+
 	protected void setPackageName(char[] packageName) {
 		this.packageName = packageName;
 	}
@@ -826,7 +839,7 @@
 	}
 
 	/**
-	 * Sets the type or package signature of the relevant
+	 * Sets the type or package or module(1.9) signature of the relevant
 	 * declaration in the context, or <code>null</code> if none.
 	 * <p>
 	 * If not set, defaults to none.
@@ -836,7 +849,7 @@
 	 * its properties; this method is not intended to be used by other clients.
 	 * </p>
 	 *
-	 * @param signature the type or package signature, or
+	 * @param signature the type or package or module(1.9) signature, or
 	 * <code>null</code> if none
 	 */
 	public void setDeclarationSignature(char[] signature) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java
index 1d2c010..16dcd1e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/MissingTypesGuesser.java
@@ -477,6 +477,10 @@
 					AccessRestriction access) {
 				// constructors aren't searched
 			}
+			@Override
+			public void acceptModule(char[] moduleName) {
+				// TODO Auto-generated method stub
+			}
 			public void acceptPackage(char[] packageName) {
 				// package aren't searched
 			}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
index 97f8a5e..eb00196 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
@@ -56,4 +56,5 @@
 	int R_TARGET = 5;
 	int R_FINAL = 3; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346
 	int R_CONSTRUCTOR = 3; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=373409
+	int R_MODULE_DECLARATION = 31;
 }
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 a975ad2..360c7cf 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -40,6 +44,7 @@
 import org.eclipse.jdt.internal.codeassist.impl.Engine;
 import org.eclipse.jdt.internal.codeassist.select.SelectionJavadocParser;
 import org.eclipse.jdt.internal.codeassist.select.SelectionNodeFound;
+import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageVisibilityReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnImportReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnQualifiedTypeReference;
@@ -55,6 +60,9 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -75,12 +83,14 @@
 import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 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.ParameterizedTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -1015,6 +1025,14 @@
 						}
 					}
 				}
+				if (parsedUnit.isModuleInfo() && parsedUnit.types != null &&
+						parsedUnit.types.length > 0) {
+					//TypeDeclaration modInfo = parsedUnit.types[0];
+					ModuleDeclaration module = parsedUnit.moduleDeclaration;//modInfo.scope.compilationUnitScope().referenceContext.moduleDeclaration ;//TODO, could be null
+					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+					acceptPackageVisibilityStatements(module.exports, parsedUnit.scope);
+					acceptPackageVisibilityStatements(module.opens, parsedUnit.scope);
+				}
 				if (parsedUnit.types != null || parsedUnit.isPackageInfo()) {
 					if(selectDeclaration(parsedUnit))
 						return;
@@ -1022,7 +1040,6 @@
 					if ((this.unitScope = parsedUnit.scope)  != null) {
 						try {
 							this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
-							
 							CompilationUnitDeclaration previousUnitBeingCompleted = this.lookupEnvironment.unitBeingCompleted;
 							this.lookupEnvironment.unitBeingCompleted = parsedUnit;
 							parsedUnit.scope.faultInTypes();
@@ -1084,6 +1101,30 @@
 		}
 	}
 
+	private void acceptPackageVisibilityStatements(PackageVisibilityStatement[] pvs, Scope scope) {
+		if (pvs != null) {
+			for (PackageVisibilityStatement pv : pvs) {
+				if (pv.pkgRef instanceof SelectionOnPackageVisibilityReference) {
+					this.noProposal = false;
+					this.requestor.acceptPackage(CharOperation.concatWith(((SelectionOnPackageVisibilityReference) pv.pkgRef).tokens, '.'));
+				}
+				if (pv.targets == null || pv.targets.length == 0) continue;
+				for (ModuleReference ref : pv.targets) {
+					acceptModuleReference(ref, scope);
+				}
+			}
+		}
+	}
+	private void acceptModuleReference(ModuleReference ref, Scope scope) {
+		try {
+			ref.resolve(scope);
+		} catch (SelectionNodeFound e) {
+			if (e.binding != null) {
+				this.noProposal = false;
+				this.requestor.acceptModule(ref.moduleName, e.binding.computeUniqueKey(), ref.sourceStart, ref.sourceEnd);
+			}
+		}
+	}
 	private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref, boolean staticOnly) {
 		int fieldLength = lastToken.length;
 		ReferenceBinding[] memberTypes = ref.memberTypes();
@@ -1349,6 +1390,14 @@
 			this.acceptedAnswer = true;
 		} else if(binding instanceof BaseTypeBinding) {
 			this.acceptedAnswer = true;
+		} else if (binding instanceof ModuleBinding) {
+			this.noProposal = false;
+			ModuleBinding moduleBinding = (ModuleBinding) binding;
+			this.requestor.acceptModule(
+					moduleBinding.moduleName,
+					moduleBinding.computeUniqueKey(),
+					this.actualSelectionStart,
+					this.actualSelectionEnd);
 		}
 	}
 	/*
@@ -1913,4 +1962,10 @@
 			return InheritDocVisitor.CONTINUE;
 		}
 	}
+
+	@Override
+	public void acceptModule(char[] moduleName) {
+		// TODO Auto-generated method stub
+		
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java
new file mode 100644
index 0000000..fb9ef34
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExportReference.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exports reference containing the cursor location.
+ * e.g.
+ *
+ *	module myModule {
+ *  exports packageo[cursor];
+ *  }
+ *
+ *	module myModule {
+ *	---> <CompleteOnExport:packageo>
+ *  }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+public class CompletionOnExportReference extends ExportsStatement {
+
+	public CompletionOnExportReference(ImportReference ref) {
+		super(ref, null);
+	}
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("<CompleteOnExport:"); //$NON-NLS-1$
+		output.append(this.pkgName);
+		return output.append('>');
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java
new file mode 100644
index 0000000..bd033ec
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModule2.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+
+public class CompletionOnKeywordModule2 extends ModuleReference implements CompletionOnKeyword {
+	private char[] token;
+	private char[][] possibleKeywords;
+
+	public CompletionOnKeywordModule2(char[] token, long pos, char[][] possibleKeywords) {
+		super(new char[][] {token}, new long[] {pos}); // dummy
+		this.token = token;
+		this.possibleKeywords = possibleKeywords;
+		this.sourceStart = (int) (pos>>>32)  ;
+		this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
+	}
+
+	@Override
+	public char[] getToken() {
+		return this.token;
+	}
+
+	@Override
+	public char[][] getPossibleKeywords() {
+		return this.possibleKeywords;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java
new file mode 100644
index 0000000..a716d73
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleDeclaration.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+
+public class CompletionOnKeywordModuleDeclaration extends ModuleDeclaration implements CompletionOnKeyword {
+
+	private char[] token;
+	private char[][] possibleKeywords;
+
+	public CompletionOnKeywordModuleDeclaration(char[] token, long pos, char[][] possibleKeywords) {
+		super(null, new char[][]{token}, new long[]{pos});
+		this.token = token;
+		this.possibleKeywords = possibleKeywords;
+	}
+
+	@Override
+	public char[] getToken() {
+		return this.token;
+	}
+
+	@Override
+	public char[][] getPossibleKeywords() {
+		return this.possibleKeywords;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java
new file mode 100644
index 0000000..620ee1f
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeywordModuleInfo.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+
+/**
+ * 
+ * This class is independent of its parent class and is in fact a dummy ExportsStatement. Used to hook
+ * into the existing module declaration type and is used as a placeholder for keyword completion. This can
+ * be any module keyword completion and not necessarily related to exports statement.
+ */
+public class CompletionOnKeywordModuleInfo extends ExportsStatement implements CompletionOnKeyword {
+	private char[] token;
+	private char[][] possibleKeywords;
+
+	public CompletionOnKeywordModuleInfo(char[] token, long pos, char[][] possibleKeywords) {
+		super(new ImportReference(new char[][] {token}, new long[] {pos}, false, 0), null); // dummy
+		this.token = token;
+		this.possibleKeywords = possibleKeywords;
+		this.sourceStart = (int) (pos>>>32)  ;
+		this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
+	}
+
+	@Override
+	public char[] getToken() {
+		return this.token;
+	}
+
+	@Override
+	public char[][] getPossibleKeywords() {
+		return this.possibleKeywords;
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java
new file mode 100644
index 0000000..c2948b3
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleDeclaration.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+
+public class CompletionOnModuleDeclaration extends ModuleDeclaration {
+
+	public CompletionOnModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) {
+		super(compilationResult, tokens, positions);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java
new file mode 100644
index 0000000..1f07a95
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnModuleReference.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+public class CompletionOnModuleReference extends ModuleReference {
+
+	public CompletionOnModuleReference(char[] ident, long pos) {
+		this(new char[][]{ident}, new long[]{pos});
+	}
+	public CompletionOnModuleReference(char[][] tokens, long[] sourcePositions) {
+		super(tokens, sourcePositions);
+	}
+
+	public ModuleBinding resolve(Scope scope) {
+		super.resolve(scope);
+//		if (this.binding != null) {
+//			throw new CompletionNodeFound(this, this.binding, scope);
+//		} else {
+			throw new CompletionNodeFound();
+		//}
+	}
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("<CompleteOnModuleReference:"); //$NON-NLS-1$
+		for (int i = 0; i < this.tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(this.tokens[i]);
+		}
+		return output.append('>');
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java
new file mode 100644
index 0000000..8c56236
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageVisibilityReference.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exports or an opens reference containing the cursor location.
+ * e.g.
+ *
+ *	module myModule {
+ *  exports packageo[cursor];
+ *  opens packageo[cursor];
+
+ *  }
+ *
+ *	module myModule {
+ *	---> <CompleteOnPackageVisibilityReference:packageo>
+ *  }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+public class CompletionOnPackageVisibilityReference extends CompletionOnImportReference {
+
+	String pkgName;
+	public CompletionOnPackageVisibilityReference(char[][] ident, long[] pos) {
+		super(ident, pos, 0);
+		this.pkgName = new String(CharOperation.concatWith(ident, '.'));
+	}
+
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output).append("<CompleteOnPackageVisibilityReference:"); //$NON-NLS-1$
+		output.append(this.pkgName);
+		return output.append('>');
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java
new file mode 100644
index 0000000..4dedd48
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsQualifiedTypeReference.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnProvidesImplementationsQualifiedTypeReference extends CompletionOnQualifiedTypeReference {
+
+	public CompletionOnProvidesImplementationsQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier,
+			long[] positions) {
+		super(previousIdentifiers, completionIdentifier, positions);
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java
new file mode 100644
index 0000000..0fc6f97
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesImplementationsSingleTypeReference.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnProvidesImplementationsSingleTypeReference extends CompletionOnSingleTypeReference {
+	public CompletionOnProvidesImplementationsSingleTypeReference(char[] source, long pos) {
+		super(source, pos);
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java
new file mode 100644
index 0000000..f0f7c63
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesQualifiedTypeReference.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnProvidesInterfacesQualifiedTypeReference extends CompletionOnQualifiedTypeReference {
+
+	public CompletionOnProvidesInterfacesQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier,
+			long[] positions) {
+		super(previousIdentifiers, completionIdentifier, positions);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java
new file mode 100644
index 0000000..adc9c7f
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnProvidesInterfacesSingleTypeReference.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnProvidesInterfacesSingleTypeReference extends CompletionOnSingleTypeReference {
+	public CompletionOnProvidesInterfacesSingleTypeReference(char[] source, long pos) {
+		super(source, pos);
+	}
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java
new file mode 100644
index 0000000..f491cf5
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesQualifiedTypeReference.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnUsesQualifiedTypeReference extends CompletionOnQualifiedTypeReference {
+
+	public CompletionOnUsesQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier,
+			long[] positions) {
+		super(previousIdentifiers, completionIdentifier, positions);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java
new file mode 100644
index 0000000..aa93f63
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnUsesSingleTypeReference.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/package org.eclipse.jdt.internal.codeassist.complete;
+
+public class CompletionOnUsesSingleTypeReference extends CompletionOnSingleTypeReference {
+
+	public CompletionOnUsesSingleTypeReference(char[] source, long pos) {
+		super(source, pos);
+	}
+}
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 8b4af64..ebf52c6 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
@@ -85,6 +85,14 @@
 	// added for https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534
 	protected static final int K_BETWEEN_INSTANCEOF_AND_RPAREN = COMPLETION_PARSER + 41;
 	protected static final int K_INSIDE_IMPORT_STATEMENT = COMPLETION_PARSER + 43;
+	protected static final int K_INSIDE_EXPORTS_STATEMENT = COMPLETION_PARSER + 44;
+	protected static final int K_INSIDE_REQUIRES_STATEMENT = COMPLETION_PARSER + 45;
+	protected static final int K_INSIDE_USES_STATEMENT = COMPLETION_PARSER + 46;
+	protected static final int K_INSIDE_PROVIDES_STATEMENT = COMPLETION_PARSER + 47;
+	protected static final int K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT = COMPLETION_PARSER + 48;
+	protected static final int K_AFTER_NAME_IN_PROVIDES_STATEMENT = COMPLETION_PARSER + 49;
+	protected static final int K_AFTER_WITH_IN_PROVIDES_STATEMENT = COMPLETION_PARSER + 50;
+	protected static final int K_INSIDE_OPENS_STATEMENT = COMPLETION_PARSER + 51;
 
 
 	public final static char[] FAKE_TYPE_NAME = new char[]{' '};
@@ -249,16 +257,17 @@
 		if (this.currentElement instanceof RecoveredUnit){
 			if (orphan instanceof ImportReference){
 				this.currentElement.add((ImportReference)orphan, 0);
+			} else if (orphan instanceof ModuleDeclaration) {
+				this.currentElement.add((ModuleDeclaration)orphan, 0);
 			}
-		}
-
-		/* if in context of a type, then persists the identifier into a fake field return type */
-		if (this.currentElement instanceof RecoveredType){
+		} else if (this.currentElement instanceof RecoveredType){	/* if in context of a type, then persists the identifier into a fake field return type */
 			RecoveredType recoveredType = (RecoveredType)this.currentElement;
 			/* filter out cases where scanner is still inside type header */
 			if (recoveredType.foundOpeningBrace) {
 				/* generate a pseudo field with a completion on type reference */
 				if (orphan instanceof TypeReference){
+					if (isInsideModuleInfo()) return; //taken care elsewhere
+
 					TypeReference fieldType;
 
 					int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
@@ -1455,6 +1464,7 @@
 private boolean checkKeyword() {
 	if (this.currentElement instanceof RecoveredUnit) {
 		RecoveredUnit unit = (RecoveredUnit) this.currentElement;
+		if (unit.unitDeclaration.isModuleInfo()) return false;
 		int index = -1;
 		if ((index = this.indexOfAssistIdentifier()) > -1) {
 			int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
@@ -1517,6 +1527,78 @@
 	}
 	return false;
 }
+
+private enum ModuleKeyword {
+	FIRST_ALL,
+	TO,
+	PROVIDES_WITH,
+	NOT_A_KEYWORD
+}
+
+private ModuleKeyword getKeyword() {
+	ModuleKeyword keyword = ModuleKeyword.FIRST_ALL;
+	if (isInModuleStatements()) {
+		if (foundToken(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT)) keyword = ModuleKeyword.TO;
+		else if (foundToken(K_AFTER_NAME_IN_PROVIDES_STATEMENT)) keyword = ModuleKeyword.PROVIDES_WITH;
+		else keyword = ModuleKeyword.NOT_A_KEYWORD;
+	}
+	return keyword;
+}
+private char[][] getModuleKeywords(ModuleKeyword keyword) {
+	if (keyword == ModuleKeyword.TO) return new char[][]{Keywords.TO};
+	else if (keyword == ModuleKeyword.PROVIDES_WITH) return new char[][]{Keywords.WITH};
+	else return new char[][]{Keywords.EXPORTS, Keywords.OPENS, Keywords.REQUIRES, Keywords.PROVIDES, Keywords.USES};
+}
+private boolean checkModuleInfoConstructs() {
+
+	if (!isInsideModuleInfo()) return false;
+
+	int index = -1;
+	if ((index = this.indexOfAssistIdentifier()) <= -1) return false;
+	
+	if (this.currentElement instanceof RecoveredModule) {
+		RecoveredModule module = (RecoveredModule) this.currentElement;
+		if (checkModuleInfoKeyword(module, index)) return true;
+	} else  {
+		ModuleKeyword keyword = ModuleKeyword.NOT_A_KEYWORD;
+		if (isInModuleStatements()) {
+			if (foundToken(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT)) keyword =  ModuleKeyword.TO;
+			if (foundToken(K_AFTER_NAME_IN_PROVIDES_STATEMENT)) keyword = ModuleKeyword.PROVIDES_WITH;
+		}
+		if (keyword == ModuleKeyword.NOT_A_KEYWORD) return false;
+		
+		int length = this.identifierLengthStack[this.identifierLengthPtr];
+		int ptr = this.identifierPtr - length + index + 1;
+		
+		char[] ident = this.identifierStack[ptr];
+		long pos = this.identifierPositionStack[ptr];		
+		char[][] keywords = getModuleKeywords(keyword);		
+		if (this.currentElement instanceof RecoveredPackageVisibilityStatement) {
+			RecoveredPackageVisibilityStatement rPvs = (RecoveredPackageVisibilityStatement) this.currentElement;
+			rPvs.add(new CompletionOnKeywordModule2(ident, pos, keywords), 0);
+			return true;
+		} else if (this.currentElement instanceof RecoveredProvidesStatement) {
+			RecoveredProvidesStatement rPs = (RecoveredProvidesStatement) this.currentElement;
+			rPs.add(new CompletionOnKeyword1(ident, pos, keywords), 0);
+			return true;
+		}
+	} 
+	return false;
+}
+private boolean checkModuleInfoKeyword(RecoveredModule module, int index) {
+	ModuleKeyword keyword = getKeyword();
+	if (keyword == ModuleKeyword.NOT_A_KEYWORD) return false;
+
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	int ptr = this.identifierPtr - length + index + 1;
+
+	char[] ident = this.identifierStack[ptr];
+	long pos = this.identifierPositionStack[ptr];
+	char[][] keywords = getModuleKeywords(keyword);
+	module.add(new CompletionOnKeywordModuleInfo(ident, pos, keywords), 0);
+	return true;
+}
+
 private boolean checkInstanceofKeyword() {
 	if(isInsideMethod()) {
 		int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
@@ -2037,6 +2119,7 @@
 
 	if (checkMemberValueName()) return;
 	if (checkKeyword()) return;
+	if (checkModuleInfoConstructs()) return;
 	if (checkRecoveredType()) return;
 	if (checkRecoveredMethod()) return;
 
@@ -2044,7 +2127,8 @@
 	if (!(isInsideMethod() && !this.diet)
 		&& !isIndirectlyInsideFieldInitialization()
 		&& !isIndirectlyInsideEnumConstantnitialization()
-		&& !isInsideAttributeValue()) return;
+		&& !isInsideAttributeValue()
+		&& !isInsideModuleInfo()) return;
 
 	/*
 	 	In some cases, the completion identifier may not have yet been consumed,
@@ -2073,6 +2157,7 @@
 	// no need to check further if we are not at the cursor location
 	if (this.indexOfAssistIdentifier() < 0) return;
 
+	if (checkModuleInfoConstructs()) return;
 	if (checkClassInstanceCreation()) return;
 	if (checkMemberAccess()) return;
 	if (checkClassLiteralAccess()) return;
@@ -3362,6 +3447,22 @@
 	this.lastModifiersStart = this.intStack[this.intPtr];
 	this.lastModifiers = 	this.intStack[this.intPtr-1];
 }
+protected void consumeModuleHeader() {
+	super.consumeModuleHeader();
+}
+protected void consumeProvidesInterface() {
+	super.consumeProvidesInterface();
+	pushOnElementStack(K_AFTER_NAME_IN_PROVIDES_STATEMENT);
+}
+protected void consumeProvidesStatement() {
+	super.consumeProvidesStatement();
+	popElement(K_INSIDE_PROVIDES_STATEMENT);
+}
+protected void consumeWithClause() {
+	super.consumeWithClause();
+	popElement(K_AFTER_WITH_IN_PROVIDES_STATEMENT);
+}
+
 protected void consumeReferenceType() {
 	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
 		// potential receiver is being poped, so reset potential receiver
@@ -3370,12 +3471,25 @@
 	}
 	super.consumeReferenceType();
 }
+protected void consumeRequiresStatement() {
+	super.consumeRequiresStatement();
+	popElement(K_INSIDE_REQUIRES_STATEMENT);
+}
 protected void consumeRestoreDiet() {
 	super.consumeRestoreDiet();
 	if (isInsideMethod()) {
 		popElement(K_LOCAL_INITIALIZER_DELIMITER);
 	}
 }
+protected void consumeExportsStatement() {
+	super.consumeExportsStatement();
+	popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT);
+	popElement(K_INSIDE_EXPORTS_STATEMENT);
+}
+protected void consumeSinglePkgName() {
+	super.consumeSinglePkgName();
+	pushOnElementStack(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT);
+}
 protected void consumeSingleMemberAnnotation(boolean isTypeAnnotation) {
 	if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
 			(this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) & ANNOTATION_NAME_COMPLETION) != 0 ) {
@@ -3574,6 +3688,21 @@
 	}
 	if (token == TokenNameimport) {
 		pushOnElementStack(K_INSIDE_IMPORT_STATEMENT);
+	}	else if (token == TokenNameexports) {
+		pushOnElementStack(K_INSIDE_EXPORTS_STATEMENT);
+	}	else if (token == TokenNameopens) {
+		pushOnElementStack(K_INSIDE_OPENS_STATEMENT);
+	}	else if (token == TokenNameto) {
+		popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT);
+	}	else if (token == TokenNamerequires) {
+		pushOnElementStack(K_INSIDE_REQUIRES_STATEMENT);
+	} else if (token == TokenNameprovides) {
+		pushOnElementStack(K_INSIDE_PROVIDES_STATEMENT);
+	} else if (token == TokenNameuses) {
+		pushOnElementStack(K_INSIDE_USES_STATEMENT);
+	}	else if (token == TokenNamewith) {
+		popElement(K_AFTER_NAME_IN_PROVIDES_STATEMENT);
+		pushOnElementStack(K_AFTER_WITH_IN_PROVIDES_STATEMENT);
 	}
 
 	// if in a method or if in a field initializer
@@ -4084,6 +4213,12 @@
 	super.consumeOpenFakeBlock();
 	pushOnElementStack(K_BLOCK_DELIMITER);
 }
+@Override
+protected void consumeOpensStatement() {
+	super.consumeOpensStatement();
+	popElement(K_AFTER_PACKAGE_IN_PACKAGE_VISIBILITY_STATEMENT);
+	popElement(K_INSIDE_OPENS_STATEMENT);
+}
 protected void consumeRightParen() {
 	super.consumeRightParen();
 }
@@ -4208,6 +4343,11 @@
 	super.consumeUnionTypeAsClassType();
 	popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
 }
+protected void consumeUsesStatement() {
+	super.consumeUsesStatement();
+	popElement(K_INSIDE_USES_STATEMENT);
+}
+
 protected void consumeWildcard() {
 	super.consumeWildcard();
 	if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
@@ -4314,9 +4454,34 @@
 	}
 	return methodDeclaration;
 }
+public ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions){
+	return new CompletionOnPackageVisibilityReference(tokens, positions);
+}
 public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
 	return new CompletionOnImportReference(tokens, positions, mod);
 }
+@Override
+public ModuleReference createAssistModuleReference(int index) {
+	/* retrieve identifiers subset and whole positions, the assist node positions
+	should include the entire replaced source. */
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	this.identifierLengthPtr--;
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+			this.identifierPositionStack,
+			this.identifierPtr + 1,
+			positions,
+			0,
+			length);
+	return new CompletionOnModuleReference(subset, positions);
+}
+@Override
+public ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens,
+		long[] positions) {
+	return new CompletionOnModuleDeclaration(compilationResult, tokens, positions);
+}
 public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
 	return new CompletionOnPackageReference(tokens, positions);
 }
@@ -4327,6 +4492,14 @@
 					positions,
 					isInsideAttributeValue());
 }
+private TypeReference checkAndCreateModuleQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions) {
+	if (isInUsesStatement()) return new CompletionOnUsesQualifiedTypeReference(previousIdentifiers, assistName, positions);
+	if (isInProvidesStatement()) {
+		if (isAfterWithClause()) return new CompletionOnProvidesImplementationsQualifiedTypeReference(previousIdentifiers, assistName, positions);
+		return new CompletionOnProvidesInterfacesQualifiedTypeReference(previousIdentifiers, assistName, positions);
+	}
+	return new CompletionOnQualifiedTypeReference(previousIdentifiers,	assistName,	positions);
+}
 public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
 	switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
 		case K_NEXT_TYPEREF_IS_EXCEPTION :
@@ -4350,7 +4523,7 @@
 					positions,
 					CompletionOnQualifiedTypeReference.K_INTERFACE);
 		default :
-			return new CompletionOnQualifiedTypeReference(
+			return checkAndCreateModuleQualifiedAssistTypeReference(
 					previousIdentifiers,
 					assistName,
 					positions);
@@ -4513,6 +4686,14 @@
 		}
 	}
 }
+private TypeReference checkAndCreateModuleSingleAssistTypeReference(char[] assistName, long position) {
+	if (isInUsesStatement()) return new CompletionOnUsesSingleTypeReference(assistName, position);
+	if (isInProvidesStatement()) {
+		if (isAfterWithClause()) return new CompletionOnProvidesImplementationsSingleTypeReference(assistName, position);
+		return new CompletionOnProvidesInterfacesSingleTypeReference(assistName, position);
+	}
+	return new CompletionOnSingleTypeReference(assistName,position);
+}
 public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
 	switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
 		case K_NEXT_TYPEREF_IS_EXCEPTION :
@@ -4524,7 +4705,7 @@
 		case K_NEXT_TYPEREF_IS_INTERFACE :
 			return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_INTERFACE);
 		default :
-			return new CompletionOnSingleTypeReference(assistName, position);
+			return checkAndCreateModuleSingleAssistTypeReference(assistName, position);
 	}
 }
 public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
@@ -5082,7 +5263,7 @@
 	this.cursorLocation = 0;
 	flushAssistState();
 }
-public void restoreAssistParser(Object parserState) {
+public void restoreAssistParser(Object parserState) { 	
 	int[] state = (int[]) parserState;
 	
 	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
@@ -5284,14 +5465,43 @@
 	}
 	return false;	
 }
-protected boolean isInImportStatement() {
+private boolean foundToken(int token) {
 	int i = this.elementPtr;
 	while (i > -1) {
-		if (this.elementKindStack[i] == K_INSIDE_IMPORT_STATEMENT) {
+		if (this.elementKindStack[i] == token) {
 			return true;
 		}
 		i--;
 	}
 	return false;
 }
+
+protected boolean isInImportStatement() {
+	return foundToken(K_INSIDE_IMPORT_STATEMENT);
+}
+protected boolean isInExportsStatement() {
+	return foundToken(K_INSIDE_EXPORTS_STATEMENT);
+}
+protected boolean isInOpensStatement() {
+	return foundToken(K_INSIDE_OPENS_STATEMENT);
+}
+protected boolean isInRequiresStatement() {
+	return foundToken(K_INSIDE_REQUIRES_STATEMENT);
+}
+protected boolean isInUsesStatement() {
+	return foundToken(K_INSIDE_USES_STATEMENT);
+}
+protected boolean isInProvidesStatement() {
+	return foundToken(K_INSIDE_PROVIDES_STATEMENT);
+}
+protected boolean isAfterWithClause() {
+	return foundToken(K_AFTER_WITH_IN_PROVIDES_STATEMENT);
+}
+protected boolean isInModuleStatements() {
+	return isInExportsStatement() ||
+			isInOpensStatement() ||
+			isInRequiresStatement() ||
+			isInProvidesStatement() ||
+			isInUsesStatement();
+}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
index 754641a..e1c14a5 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -18,6 +22,7 @@
 import java.util.HashSet;
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
@@ -35,7 +40,10 @@
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.SuperReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -46,6 +54,7 @@
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
+import org.eclipse.jdt.internal.compiler.parser.RecoveredExportsStatement;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredField;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer;
 import org.eclipse.jdt.internal.compiler.parser.RecoveredLocalVariable;
@@ -95,7 +104,8 @@
 	protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
 	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
 	protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression
-	
+	protected static final int K_MODULE_INFO_DELIMITER = ASSIST_PARSER + 8; // whether we are inside a module info declaration
+
 	// selector constants
 	protected static final int THIS_CONSTRUCTOR = -1;
 	protected static final int SUPER_CONSTRUCTOR = -2;
@@ -103,7 +113,7 @@
 	// enum constant constants
 	protected static final int NO_BODY = 0;
 	protected static final int WITH_BODY = 1;
-	
+
 	protected static final int EXPRESSION_BODY = 0;
 	protected static final int BLOCK_BODY = 1;
 
@@ -179,6 +189,7 @@
 		flushAssistState();
 		flushElementStack();
 		this.snapShot = null;
+		initModuleInfo(element);
 		return element;
 	}
 
@@ -365,6 +376,22 @@
 
 	return element;
 }
+
+private void initModuleInfo(RecoveredElement element) {
+	if (element  instanceof RecoveredUnit) {
+		RecoveredUnit unit = (RecoveredUnit) element;
+		if (unit.unitDeclaration.isModuleInfo()) {
+			ASTNode node = null;
+			int i = 0;
+			for (; i <= this.astPtr; i++) {
+				if ((node = this.astStack[i]) instanceof ModuleDeclaration) {
+					unit.add((ModuleDeclaration) node, this.bracketDepth); 
+					break;
+				}
+			}
+		}
+	}
+}
 protected void consumeAnnotationTypeDeclarationHeader() {
 	super.consumeAnnotationTypeDeclarationHeader();
 	pushOnElementStack(K_TYPE_DELIMITER);
@@ -686,6 +713,57 @@
 		this.lastCheckPoint = messageSend.sourceEnd + 1;
 	}
 }
+protected void consumeModuleHeader() {
+	pushOnElementStack(K_MODULE_INFO_DELIMITER);
+	// ModuleHeader ::= 'module' Name
+	/* build an ImportRef build from the last name
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeModuleHeader();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+	should include the entire replaced source. */
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	this.identifierLengthPtr--;
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+			this.identifierPositionStack,
+			this.identifierPtr + 1,
+			positions,
+			0,
+			length);
+	ModuleDeclaration typeDecl = createAssistModuleDeclaration(this.compilationUnit.compilationResult, subset, positions);
+
+	this.compilationUnit.moduleDeclaration = typeDecl;
+	this.assistNode = typeDecl;
+	this.lastCheckPoint = typeDecl.sourceEnd + 1;
+
+	//compute the declaration source too
+	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
+
+	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+	pushOnAstStack(typeDecl);
+
+	this.listLength = 0; // will be updated when reading super-interfaces
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = typeDecl.bodyStart;
+		this.currentElement = this.currentElement.add(typeDecl, 0);
+		this.lastIgnoredToken = -1;
+	}
+}
+
+protected void consumeModuleDeclaration() {
+	super.consumeModuleDeclaration();
+	popElement(K_MODULE_INFO_DELIMITER);
+}
 protected void consumeNestedMethod() {
 	super.consumeNestedMethod();
 	if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
@@ -899,6 +977,104 @@
 		this.restartRecovery = true; // used to avoid branching back into the regular automaton
 	}
 }
+protected void consumeSinglePkgName() {
+	int index;
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeSinglePkgName();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+	should include the entire replaced source. */
+	int length = this.identifierLengthStack[this.identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	this.identifierLengthPtr--;
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+			this.identifierPositionStack,
+			this.identifierPtr + 1,
+			positions,
+			0,
+			length);
+
+	/* build specific assist node on import statement */
+	ImportReference reference = createAssistPackageVisibilityReference(subset, positions);
+	this.assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+
+	pushOnAstStack(reference);
+
+	if (this.currentToken == TokenNameSEMICOLON) {
+		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+}
+protected void consumeSingleTargetModuleName() {
+	int index;
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeSingleTargetModuleName();
+		return;
+	}
+
+	/* build specific assist node on targetted exports statement */
+	ModuleReference reference = createAssistModuleReference(index);
+	this.assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+	pushOnAstStack(reference);
+
+	// recovery - TBD
+	if (this.currentElement instanceof RecoveredExportsStatement){
+		// TODO
+		this.lastCheckPoint = reference.sourceEnd+1;
+		this.currentElement = ((RecoveredExportsStatement) this.currentElement).add(reference, 0);
+		this.lastIgnoredToken = -1;
+		//this.restartRecovery = true; // used to avoid branching back into the regular automaton
+	}
+
+}
+protected void consumeSingleRequiresModuleName() {
+
+	int index = indexOfAssistIdentifier();
+	/* no need to take action if not inside assist identifiers */
+	if (index < 0) {
+		super.consumeSingleRequiresModuleName();
+		return;
+	}
+
+	/* build specific assist node on requires statement */
+	ModuleReference reference = createAssistModuleReference(index);
+	this.assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+	RequiresStatement req = new RequiresStatement(reference);
+	if (this.currentToken == TokenNameSEMICOLON){
+		req.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		req.declarationSourceEnd = reference.sourceEnd;
+	}
+	req.sourceStart = req.declarationSourceStart;
+	req.declarationEnd = req.declarationSourceEnd;
+	req.modifiersSourceStart = this.intStack[this.intPtr--];
+	req.modifiers |= this.intStack[this.intPtr--];
+	req.declarationSourceStart = this.intStack[this.intPtr--];
+	if (req.modifiersSourceStart >= 0) {
+		req.declarationSourceStart = req.modifiersSourceStart;
+	}
+	req.sourceEnd = reference.sourceEnd;
+	pushOnAstStack(req);
+
+	// recovery TBD
+
+	if (this.currentElement != null){
+		this.lastCheckPoint = req.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.add(req, 0);
+		this.lastIgnoredToken = -1;
+	}
+
+}
+
 protected void consumeSingleTypeImportDeclarationName() {
 	// SingleTypeImportDeclarationName ::= 'import' Name
 	/* push an ImportRef build from the last name
@@ -1012,6 +1188,20 @@
 	super.consumeStaticOnly();
 	pushOnElementStack(K_METHOD_DELIMITER);
 }
+private void adjustBracket(int token) {
+	switch (token) {
+		case TokenNameLPAREN :
+		case TokenNameLBRACE:
+		case TokenNameLBRACKET:
+			this.bracketDepth++;
+			break;
+		case TokenNameRBRACE:
+		case TokenNameRBRACKET:
+		case TokenNameRPAREN:
+			this.bracketDepth--;
+			break;
+	}
+}
 protected void consumeToken(int token) {
 	super.consumeToken(token);
 
@@ -1024,7 +1214,6 @@
 	if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue() || isInsideEnumConstantnitialization()) {
 		switch (token) {
 			case TokenNameLPAREN :
-				this.bracketDepth++;
 				switch (this.previousToken) {
 					case TokenNameIdentifier:
 						this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
@@ -1049,21 +1238,10 @@
 					popElement(K_LAMBDA_EXPRESSION_DELIMITER);
 					pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo);
 				}
-				this.bracketDepth++;
-				break;
-			case TokenNameLBRACKET:
-				this.bracketDepth++;
-				break;
-			case TokenNameRBRACE:
-				this.bracketDepth--;
-				break;
-			case TokenNameRBRACKET:
-				this.bracketDepth--;
-				break;
-			case TokenNameRPAREN:
-				this.bracketDepth--;
 				break;
 		}
+	} else if (isInsideModuleInfo()) { 
+		adjustBracket(token);
 	} else {
 		switch (token) {
 			case TokenNameRBRACE :
@@ -1132,7 +1310,11 @@
 		this.restartRecovery = true; // used to avoid branching back into the regular automaton
 	}
 }
+
+// TODO : Change to ExportsReference/PackageReference once we have the new compiler ast.node
+public abstract ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions);
 public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod);
+public abstract ModuleReference createAssistModuleReference(int index);
 public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
 public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
 public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
@@ -1140,6 +1322,7 @@
 public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
 public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
 public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position);
+public abstract ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions);
 /*
  * Flush parser/scanner state regarding to code assist
  */
@@ -1535,6 +1718,21 @@
 	}
 	return false;
 }
+protected boolean isInsideModuleInfo(){
+	int i = this.elementPtr;
+	while(i > -1) {
+		switch (this.elementKindStack[i]) {
+			case K_TYPE_DELIMITER : 
+			case K_METHOD_DELIMITER :
+			case K_FIELD_INITIALIZER_DELIMITER : 
+				return false;
+			case K_MODULE_INFO_DELIMITER:
+				return true;
+		}
+		i--;
+	}
+	return false;
+}
 protected boolean isInsideMethod(){
 	int i = this.elementPtr;
 	while(i > -1) {
@@ -2087,6 +2285,12 @@
 			goForBlockStatementsopt();
 		} else {
 			prepareForHeaders();
+			if (this.referenceContext instanceof CompilationUnitDeclaration) {
+				CompilationUnitDeclaration unit = (CompilationUnitDeclaration) this.referenceContext;
+				if (unit.isModuleInfo()) {
+					pushOnElementStack(K_MODULE_INFO_DELIMITER);
+				}
+			}
 			goForHeaders();
 			this.diet = true; // passed this point, will not consider method bodies
 			this.dietInt = 0;
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
index 79c4c7f..e905601 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.codeassist.impl;
 
 public interface Keywords {
-	int COUNT = 41;
+	int COUNT = 49;
 
 	char[] ABSTRACT = "abstract".toCharArray(); //$NON-NLS-1$
 	char[] ASSERT = "assert".toCharArray(); //$NON-NLS-1$
@@ -25,20 +25,25 @@
 	char[] ELSE = "else".toCharArray(); //$NON-NLS-1$
 	char[] ENUM = "enum".toCharArray(); //$NON-NLS-1$
 	char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
+	char[] EXPORTS = "exports".toCharArray(); //$NON-NLS-1$
 	char[] FINAL = "final".toCharArray(); //$NON-NLS-1$
 	char[] FINALLY = "finally".toCharArray(); //$NON-NLS-1$
 	char[] FOR = "for".toCharArray(); //$NON-NLS-1$
 	char[] IF = "if".toCharArray(); //$NON-NLS-1$
 	char[] IMPLEMENTS = "implements".toCharArray(); //$NON-NLS-1$
 	char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$
+	char[] MODULE = "module".toCharArray(); //$NON-NLS-1$
 	char[] INSTANCEOF = "instanceof".toCharArray(); //$NON-NLS-1$
 	char[] INTERFACE = "interface".toCharArray(); //$NON-NLS-1$
 	char[] NATIVE = "native".toCharArray(); //$NON-NLS-1$
 	char[] NEW = "new".toCharArray(); //$NON-NLS-1$
+	char[] OPENS= "opens".toCharArray(); //$NON-NLS-1$
 	char[] PACKAGE = "package".toCharArray(); //$NON-NLS-1$
 	char[] PRIVATE = "private".toCharArray(); //$NON-NLS-1$
 	char[] PROTECTED = "protected".toCharArray(); //$NON-NLS-1$
+	char[] PROVIDES = "provides".toCharArray(); //$NON-NLS-1$
 	char[] PUBLIC = "public".toCharArray(); //$NON-NLS-1$
+	char[] REQUIRES = "requires".toCharArray(); //$NON-NLS-1$
 	char[] RETURN = "return".toCharArray(); //$NON-NLS-1$
 	char[] STATIC = "static".toCharArray(); //$NON-NLS-1$
 	char[] STRICTFP = "strictfp".toCharArray(); //$NON-NLS-1$
@@ -48,10 +53,13 @@
 	char[] THIS = "this".toCharArray(); //$NON-NLS-1$
 	char[] THROW = "throw".toCharArray(); //$NON-NLS-1$
 	char[] THROWS = "throws".toCharArray(); //$NON-NLS-1$
+	char[] TO = "to".toCharArray(); //$NON-NLS-1$
 	char[] TRANSIENT = "transient".toCharArray(); //$NON-NLS-1$
 	char[] TRY = "try".toCharArray(); //$NON-NLS-1$
+	char[] USES = "uses".toCharArray(); //$NON-NLS-1$
 	char[] VOLATILE = "volatile".toCharArray(); //$NON-NLS-1$
 	char[] WHILE = "while".toCharArray(); //$NON-NLS-1$
+	char[] WITH = "with".toCharArray(); //$NON-NLS-1$
 	char[] TRUE = "true".toCharArray(); //$NON-NLS-1$
 	char[] FALSE = "false".toCharArray(); //$NON-NLS-1$
 	char[] NULL = "null".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java
new file mode 100644
index 0000000..f325224
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleDeclaration.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+
+public class SelectionOnModuleDeclaration extends ModuleDeclaration {
+
+	public SelectionOnModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) {
+		super(compilationResult, tokens, positions);
+	}
+	public void resolve(ClassScope scope) {
+		super.resolve(scope);
+		throw new SelectionNodeFound(this.moduleBinding);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java
new file mode 100644
index 0000000..a0a5088
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnModuleReference.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+public class SelectionOnModuleReference extends ModuleReference {
+
+	public SelectionOnModuleReference(char[][] tokens, long[] sourcePositions) {
+		super(tokens, sourcePositions);
+	}
+
+	public ModuleBinding resolve(Scope scope) {
+		ModuleBinding binding = super.resolve(scope);
+		if (binding != null) {
+			throw new SelectionNodeFound(binding);
+		} else {
+			throw new SelectionNodeFound();
+		}
+	}
+
+	public StringBuffer print(int tab, StringBuffer output) {
+		printIndent(tab, output).append("<SelectOnModuleReference:"); //$NON-NLS-1$
+		for (int i = 0; i < this.tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(this.tokens[i]);
+		}
+		return output.append('>');
+	}
+
+}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java
new file mode 100644
index 0000000..75a980f
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageVisibilityReference.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.select;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an export reference containing the assist identifier.
+ * e.g.
+ *
+ *	module myModule {
+ *  exports packageo[cursor];
+ *  }
+ *
+ *	module myModule {
+ *	---> <SelectionOnExport:packageo>
+ *  }
+ *
+ */
+public class SelectionOnPackageVisibilityReference extends ImportReference {
+
+	public SelectionOnPackageVisibilityReference(char[][] tokens, long[] positions) {
+		super(tokens, positions, false, 0);
+	}
+
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("<SelectOnPackageVisibility:"); //$NON-NLS-1$
+		output.append(new String(CharOperation.concatWith(this.tokens, '.')));
+		return output.append('>');
+	}
+}
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 3c511ca..b3392e2 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
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -41,6 +45,8 @@
 import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
@@ -1258,9 +1264,17 @@
 protected SelectionParser createSnapShotParser() {
 	return new SelectionParser(this.problemReporter);
 }
+public ImportReference createAssistPackageVisibilityReference(char[][] tokens, long[] positions){
+	return new SelectionOnPackageVisibilityReference(tokens, positions);
+}
 public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
 	return new SelectionOnImportReference(tokens, positions, mod);
 }
+@Override
+public ModuleDeclaration createAssistModuleDeclaration(CompilationResult compilationResult, char[][] tokens,
+		long[] positions) {
+	return new SelectionOnModuleDeclaration(compilationResult, tokens, positions);
+}
 public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
 	return new SelectionOnPackageReference(tokens, positions);
 }
@@ -1591,4 +1605,17 @@
 	s = s + "}\n"; //$NON-NLS-1$
 	return s + super.toString();
 }
+@Override
+public ModuleReference createAssistModuleReference(int index) {
+	// ignore index, all segments of the module name are part of a single identifier.
+	/* retrieve identifiers subset and whole positions, the assist node positions
+	should include the entire replaced source. */
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	return new SelectionOnModuleReference(tokens, positions);
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
index 23b3817..7cffb92 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Luiz-Otavio Zorzella <zorzella at gmail dot com> - Improve CamelCase algorithm
@@ -41,6 +45,18 @@
 	 */
 	public static final String[] NO_STRINGS = new String[0];
 
+	/**
+	 * Constant for all Prefix
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final char[] ALL_PREFIX = new char[] {'*'};
+
+	/**
+	 * Constant for comma
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final char[] COMMA_SEPARATOR = new char[] {','};
+
 /**
  * Answers a new array with appending the suffix character at the end of the array.
  * <br>
@@ -1165,6 +1181,77 @@
 }
 
 /**
+ * Answers the concatenation of the two arrays inserting the separator character between the two arrays. Differs from
+ * {@link CharOperation#contains(char, char[])} in case second array is a zero length array.
+ * It answers null if the two arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ * if the second array is zero length array, the separator is appended.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ *    first = null
+ *    second = { 'a' }
+ *    separator = '/'
+ *    => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { ' a' }
+ *    second = null
+ *    separator = '/'
+ *    => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { ' a' }
+ *    second = { ' b' }
+ *    separator = '/'
+ *    => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { ' a' }
+ *    second = { '' }
+ *    separator = '.'
+ *    => result = { ' a' , '.', }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first the first array to concatenate
+ * @param second the second array to concatenate
+ * @param separator the character to insert
+ * @return the concatenation of the two arrays inserting the separator character
+ * between the two arrays , or null if the two arrays are null. If second array
+ * is of zero length, the separator is appended to the first array and returned.
+ * @since 3.13 BETA_JAVA9
+ */
+public static final char[] concatAll(
+	char[] first,
+	char[] second,
+	char separator) {
+	if (first == null)
+		return second;
+	if (second == null)
+		return first;
+
+	int length1 = first.length;
+	if (length1 == 0)
+		return second;
+	int length2 = second.length;
+
+	char[] result = new char[length1 + length2 + 1];
+	System.arraycopy(first, 0, result, 0, length1);
+	result[length1] = separator;
+	if (length2 > 0)
+		System.arraycopy(second, 0, result, length1 + 1, length2);
+	return result;
+}
+
+/**
  * Answers the concatenation of the three arrays inserting the sep1 character between the
  * first two arrays and sep2 between the last two.
  * It answers null if the three arrays are null.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 12f6fe0..e5f6878 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     IBM Corporation - added the following constants
@@ -363,9 +367,14 @@
 	 */
 	int IgnoreCategoriesMask = 0xFFFFFF;
 
-	/**
+	/*
 	 * Below are listed all available problem IDs. Note that this list could be augmented in the future,
 	 * as new features are added to the Java core implementation.
+	 *
+	 * Problem IDs must be kept unique even when their mask is stripped, since
+	 * the bare integer literal is used for message lookup in
+	 * /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties.
+	 * Use this regex to find duplicates: (?s)(\+ \d+)\b.*\1\b
 	 */
 
 	/**
@@ -1476,6 +1485,8 @@
     int InterfaceSuperInvocationNotBelow18 = Internal + Syntax + 667;
     /** @since 3.13*/
     int InterfaceStaticMethodInvocationNotBelow18 = Internal + Syntax + 668;
+	/** @since 3.13 */
+	int FieldMustBeFinal = Internal + 669;
 
 
 	/**
@@ -1673,6 +1684,8 @@
 	/** @since 3.10 */
 	int RepeatedAnnotationWithContainerAnnotation = TypeRelated + 899;
 	
+	/** @since 3.13 BETA_JAVA9 */
+	int AutoManagedVariableResourceNotBelow9 = Syntax + Internal + 876;
 	/**
 	 * External problems -- These are problems defined by other plugins
 	 */
@@ -1871,11 +1884,58 @@
 	/** @since 3.13 */
 	int CannotInferInvocationType = TypeRelated + 1059;
 	
+	
 	/** @since 3.13 */
 	int TypeAnnotationAtQualifiedName = Internal + Syntax + 1060;
 
 	/** @since 3.13 */
 	int NullAnnotationAtQualifyingType = Internal + Syntax + 1061;
+	
+	/** @since 3.13 BETA_JAVA9*/
+	int IllegalModifierForInterfaceMethod9 = MethodRelated + 1071;
+	/** @since 3.13 BETA_JAVA9*/
+	int IllegalModifierCombinationForPrivateInterfaceMethod9 = MethodRelated + 1070;
+	/** @since 3.13 BETA_JAVA9 */
+	int UndefinedModule = TypeRelated + 1300;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateRequires = TypeRelated + 1301;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateExports = TypeRelated + 1302;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateUses = TypeRelated + 1303;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateServices = TypeRelated + 1304;
+	/** @since 3.13 BETA_JAVA9 */
+	int CyclicModuleDependency = TypeRelated + 1305;
+	/** @since 3.13 BETA_JAVA9 */
+	int AbstractServiceImplementation = TypeRelated + 1306;
+	/** @since 3.13 BETA_JAVA9 */
+	int ProviderMethodOrConstructorRequiredForServiceImpl = TypeRelated + 1307;
+	/** @since 3.13 BETA_JAVA9 */
+	int ServiceImplDefaultConstructorNotPublic = TypeRelated + 1308;
+	/** @since 3.13 BETA_JAVA9 */
+	int NestedServiceImpl = TypeRelated + 1309;
+	/** @since 3.13 BETA_JAVA9 */
+	int ServiceImplNotDefinedByModule = TypeRelated + 1310;
+	/** @since 3.13 BETA_JAVA9 */
+	int PackageDoesNotExistOrIsEmpty = TypeRelated + 1311;
+	/** @since 3.13 BETA_JAVA9 */
+	int NonDenotableTypeArgumentForAnonymousDiamond = TypeRelated + 1312;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateOpens = TypeRelated + 1313;
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateModuleRef = TypeRelated + 1314;
+	/** @since 3.13 BETA_JAVA9 */
+	int InvalidOpensStatement = TypeRelated + 1315;
+	/** @since 3.13 BETA_JAVA9 */
+	int InvalidServiceIntfType = TypeRelated + 1316;
+	/** @since 3.13 BETA_JAVA9 */
+	int InvalidServiceImplType = TypeRelated + 1317;
+	/** @since 3.13 BETA_JAVA9 */
+	int IllegalModifierForModule = TypeRelated + 1318;
+
+	/** @since 3.13 BETA_JAVA9 */
+	int DuplicateResource = Internal + 1251;
 
 	/** @since 3.13 */
 	int RedundantNullDefaultAnnotationLocal = Internal + 1062;
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 906bac8..106a447 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contributions for
@@ -50,6 +54,7 @@
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
@@ -57,10 +62,13 @@
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.ast.Receiver;
 import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
 import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -90,6 +98,7 @@
 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.ModuleBinding;
 import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
@@ -174,6 +183,8 @@
 	 * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
 	 */
 	public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
+		if (typeDeclaration.isModuleInfo())
+			return; //TODO No idea what a problem module declaration should look like
 		SourceTypeBinding typeBinding = typeDeclaration.binding;
 		ClassFile classFile = ClassFile.getNewInstance(typeBinding);
 		classFile.initialize(typeBinding, null, true);
@@ -351,6 +362,9 @@
 			// to the @fieldBinding
 			attributesNumber += generateDeprecatedAttribute();
 		}
+		if (this.referenceBinding.isModule()) {
+			attributesNumber += generateModuleAttribute();
+		}
 		// add signature attribute
 		char[] genericSignature = this.referenceBinding.genericSignature();
 		if (genericSignature != null) {
@@ -370,6 +384,8 @@
 					long targetMask;
 					if (typeDeclaration.isPackageInfo())
 						targetMask = TagBits.AnnotationForPackage;
+					else if (this.referenceBinding.isModule()) // TODO: add isModuleInfo() to TypeDeclaration
+						targetMask = TagBits.AnnotationForModule;
 					else if (this.referenceBinding.isAnnotationType())
 						targetMask = TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType;
 					else
@@ -2345,7 +2361,11 @@
 	 * @return char[]
 	 */
 	public char[] fileName() {
-		return this.constantPool.UTF8Cache.returnKeyFor(2);
+		// TODO Is there a better way of doing this?
+		char[] name = this.constantPool.UTF8Cache.returnKeyFor(2);
+		if (CharOperation.endsWith(name, TypeConstants.MODULE_INFO_FILE_NAME))
+			return TypeConstants.MODULE_INFO_NAME;
+		return name;
 	}
 
 	private void generateAnnotation(Annotation annotation, int currentOffset) {
@@ -2583,6 +2603,232 @@
 		this.contentsOffset = localContentsOffset;
 		return 1;
 	}
+	private int generateModuleAttribute() {
+		ModuleDeclaration module = this.referenceBinding.scope.compilationUnitScope().referenceContext.moduleDeclaration;
+		ModuleBinding binding = module.moduleBinding;
+		int localContentsOffset = this.contentsOffset;
+		if (localContentsOffset + 10 >= this.contents.length) {
+			resizeContents(10);
+		}
+		int moduleAttributeNameIndex =
+			this.constantPool.literalIndex(AttributeNamesConstants.ModuleName);
+		this.contents[localContentsOffset++] = (byte) (moduleAttributeNameIndex >> 8);
+		this.contents[localContentsOffset++] = (byte) moduleAttributeNameIndex;
+		int attrLengthOffset = localContentsOffset;
+		localContentsOffset += 4;
+		int moduleNameIndex =
+				this.constantPool.literalIndexForModule(binding.moduleName);
+		this.contents[localContentsOffset++] = (byte) (moduleNameIndex >> 8);
+		this.contents[localContentsOffset++] = (byte) moduleNameIndex;
+		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;
+		int attrLength = 6;
+		
+		// ================= requires section =================
+		/** u2 requires_count;
+	    	{   u2 requires_index;
+	        	u2 requires_flags;
+	    	} requires[requires_count];
+	    **/
+		int requiresCountOffset = localContentsOffset;
+		int requiresCount = module.requiresCount;
+		int requiresSize = 2 + requiresCount * 6;
+		if (localContentsOffset + requiresSize >= this.contents.length) {
+			resizeContents(requiresSize);
+		}
+		
+		localContentsOffset += 2;
+		ModuleBinding javaBaseBinding = null;
+		for(int i = 0; i < module.requiresCount; i++) {
+			RequiresStatement req = module.requires[i];
+			ModuleBinding reqBinding = binding.environment.getModule(req.module.moduleName);
+			if (CharOperation.equals(req.module.moduleName, TypeConstants.JAVA_BASE)) {
+				javaBaseBinding = reqBinding;
+			}
+			int nameIndex = this.constantPool.literalIndexForModule(reqBinding.moduleName);
+			this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) (nameIndex);
+			flags = req.modifiers;
+			this.contents[localContentsOffset++] = (byte) (flags >> 8);
+			this.contents[localContentsOffset++] = (byte) (flags);
+			int required_version = 0;
+			this.contents[localContentsOffset++] = (byte) (required_version >> 8);
+			this.contents[localContentsOffset++] = (byte) (required_version);
+		}
+		if (javaBaseBinding == null) {
+			if (localContentsOffset + 6 >= this.contents.length) {
+				resizeContents(6);
+			}
+			javaBaseBinding = binding.environment.getModule(TypeConstants.JAVA_BASE);
+			int javabase_index = this.constantPool.literalIndexForModule(javaBaseBinding.moduleName);
+			this.contents[localContentsOffset++] = (byte) (javabase_index >> 8);
+			this.contents[localContentsOffset++] = (byte) (javabase_index);
+			flags = ClassFileConstants.AccMandated;
+			this.contents[localContentsOffset++] = (byte) (flags >> 8);
+			this.contents[localContentsOffset++] = (byte) flags;
+			int required_version = 0;
+			this.contents[localContentsOffset++] = (byte) (required_version >> 8);
+			this.contents[localContentsOffset++] = (byte) (required_version);
+			requiresCount++;
+		}
+		this.contents[requiresCountOffset++] = (byte) (requiresCount >> 8);
+		this.contents[requiresCountOffset++] = (byte) requiresCount;
+		attrLength += 2 + 6 * requiresCount;
+		// ================= end requires section =================
+
+		// ================= exports section =================
+		/**
+		 * u2 exports_count;
+		 * {   u2 exports_index;
+		 *     u2 exports_flags;
+		 *     u2 exports_to_count;
+		 *     u2 exports_to_index[exports_to_count];
+		 * } exports[exports_count];
+		 */
+		int exportsSize = 2 + module.exportsCount * 6;
+		if (localContentsOffset + exportsSize >= this.contents.length) {
+			resizeContents(exportsSize);
+		}
+		this.contents[localContentsOffset++] = (byte) (module.exportsCount >> 8);
+		this.contents[localContentsOffset++] = (byte) module.exportsCount;
+		for (int i = 0; i < module.exportsCount; i++) {
+			ExportsStatement ref = module.exports[i];
+			int nameIndex = this.constantPool.literalIndexForPackage(CharOperation.replaceOnCopy(ref.pkgName, '.', '/'));
+			this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) (nameIndex);
+			// TODO exports_flags - check when they are set
+			this.contents[localContentsOffset++] = (byte) 0;
+			this.contents[localContentsOffset++] = (byte) 0;
+
+			int exportsToCount = ref.isQualified() ? ref.targets.length : 0; 
+			this.contents[localContentsOffset++] = (byte) (exportsToCount >> 8);
+			this.contents[localContentsOffset++] = (byte) (exportsToCount);
+			if (exportsToCount > 0) {
+				int targetSize = 2 * exportsToCount;
+				if (localContentsOffset + targetSize >= this.contents.length) {
+					resizeContents(targetSize);
+				}
+				for(int j = 0; j < exportsToCount; j++) {
+					nameIndex = this.constantPool.literalIndexForModule(ref.targets[j].moduleName);
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) (nameIndex);
+				}
+				attrLength += targetSize;
+			}
+		}
+		attrLength += exportsSize;
+		// ================= end exports section =================
+
+		// ================= opens section =================
+		/**
+		 * u2 opens_count;
+		 * {   u2 opens_index;
+		 *     u2 opens_flags;
+		 *     u2 opens_to_count;
+		 *     u2 opens_to_index[opens_to_count];
+		 * } exports[exports_count];
+		 */
+		int opensSize = 2 + module.opensCount * 6;
+		if (localContentsOffset + opensSize >= this.contents.length) {
+			resizeContents(opensSize);
+		}
+		this.contents[localContentsOffset++] = (byte) (module.opensCount >> 8);
+		this.contents[localContentsOffset++] = (byte) module.opensCount;
+		for (int i = 0; i < module.opensCount; i++) {
+			OpensStatement ref = module.opens[i];
+			int nameIndex = this.constantPool.literalIndexForPackage(CharOperation.replaceOnCopy(ref.pkgName, '.', '/'));
+			this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) (nameIndex);
+			// TODO opens_flags - check when they are set
+			this.contents[localContentsOffset++] = (byte) 0;
+			this.contents[localContentsOffset++] = (byte) 0;
+			
+			int opensToCount = ref.isQualified() ? ref.targets.length : 0; 
+			this.contents[localContentsOffset++] = (byte) (opensToCount >> 8);
+			this.contents[localContentsOffset++] = (byte) (opensToCount);
+			if (opensToCount > 0) {
+				int targetSize = 2 * opensToCount;
+				if (localContentsOffset + targetSize >= this.contents.length) {
+					resizeContents(targetSize);
+				}
+				for(int j = 0; j < opensToCount; j++) {
+					nameIndex = this.constantPool.literalIndexForModule(ref.targets[j].moduleName);
+					this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					this.contents[localContentsOffset++] = (byte) (nameIndex);
+				}
+				attrLength += targetSize;
+			}
+		}
+		attrLength += opensSize;
+		// ================= end opens section =================
+
+		// ================= uses section =================
+		/**
+		 * u2 uses_count;
+		 * u2 uses_index[uses_count];
+		 */
+		int usesSize = 2 + 2 * module.usesCount;
+		if (localContentsOffset + usesSize >= this.contents.length) {
+			resizeContents(usesSize);
+		}
+		this.contents[localContentsOffset++] = (byte) (module.usesCount >> 8);
+		this.contents[localContentsOffset++] = (byte) module.usesCount;
+		for(int i = 0; i < module.usesCount; i++) {
+			int nameIndex = this.constantPool.literalIndexForType(module.uses[i].serviceInterface.resolvedType.constantPoolName());
+			this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) (nameIndex);
+		}
+		attrLength += usesSize;
+		// ================= end uses section =================
+
+		// ================= provides section =================
+		/**
+		 * u2 provides_count;
+		 * {
+		 * 		u2 provides_index;
+		 * 		u2 provides_with_count;
+		 * 		u2 provides_with_index[provides_with_count];
+		 * } provides[provides_count];
+		 */
+		int servicesSize = 2 + 4 * module.servicesCount;
+		if (localContentsOffset + servicesSize >= this.contents.length) {
+			resizeContents(servicesSize);
+		}
+		this.contents[localContentsOffset++] = (byte) (module.servicesCount >> 8);
+		this.contents[localContentsOffset++] = (byte) module.servicesCount;
+		for(int i = 0; i < module.servicesCount; i++) {
+			int nameIndex = this.constantPool.literalIndexForType(module.services[i].serviceInterface.resolvedType.constantPoolName());
+			this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			this.contents[localContentsOffset++] = (byte) (nameIndex);
+			TypeReference[] impls = module.services[i].implementations;
+			int implLength = impls.length;
+			this.contents[localContentsOffset++] = (byte) (implLength >> 8);
+			this.contents[localContentsOffset++] = (byte) implLength;
+			int targetSize = implLength * 2;
+			if (localContentsOffset + targetSize >= this.contents.length) {
+				resizeContents(targetSize);
+			}
+			for (int j = 0; j < implLength; j++) {
+				nameIndex = this.constantPool.literalIndexForType(impls[j].resolvedType.constantPoolName());
+				this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+				this.contents[localContentsOffset++] = (byte) (nameIndex);
+			}
+			attrLength += targetSize;
+		}
+		attrLength += servicesSize;
+		// ================= end provides section =================
+
+		this.contents[attrLengthOffset++] = (byte)(attrLength >> 24);
+		this.contents[attrLengthOffset++] = (byte)(attrLength >> 16);
+		this.contents[attrLengthOffset++] = (byte)(attrLength >> 8);
+		this.contents[attrLengthOffset++] = (byte)attrLength;
+		this.contentsOffset = localContentsOffset;
+		return 1;
+	}
 	private void generateElementValue(
 			Expression defaultValue,
 			TypeBinding memberValuePairReturnType,
@@ -4953,7 +5199,7 @@
 					| ClassFileConstants.AccNative);
 
 		// set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
-		if (!aType.isInterface()) { // class or enum
+		if (!aType.isInterface() && !aType.isModule()) { // class or enum
 			accessFlags |= ClassFileConstants.AccSuper;
 		}
 		if (aType.isAnonymousType()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 856a911..0da08b1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995
@@ -62,6 +66,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
@@ -285,6 +290,7 @@
 	// for import reference
 	public static final int OnDemand = Bit18;
 	public static final int Used = Bit2;
+	public static final int inModule = Bit19;
 
 	// for parameterized qualified/single type ref
 	public static final int DidResolve = Bit19;
@@ -773,6 +779,11 @@
 					// deliberately don't set the annotation resolved tagbits, it is not material and also we are working with a dummy static object.
 					annotations = new AnnotationBinding[length];
 					break;
+				case Binding.MODULE:
+					ModuleBinding module = (ModuleBinding)recipient;
+					if ((module.tagBits & TagBits.AnnotationResolved) != 0) return annotations;
+					module.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
+					break;
 				default :
 					return annotations;
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 25abe90..0546eaa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -591,15 +591,21 @@
 		if (constructorTypeArguments.length > 0)
 			System.arraycopy(((ParameterizedGenericMethodBinding)factory).typeArguments, sfmb.typeVariables().length - constructorTypeArguments.length , 
 												constructorTypeArguments, 0, constructorTypeArguments.length);
+		if (allocationType.isInterface()) {
+			ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) factory.returnType;
+			return new ParameterizedMethodBinding(parameterizedType, sfmb.getConstructor());
+		}
 		return sfmb.applyTypeArgumentsOnConstructor(((ParameterizedTypeBinding)factory.returnType).arguments, constructorTypeArguments, genericFactory.inferredWithUncheckedConversion);
 	}
 	return null;
 }
-
 public TypeBinding[] inferElidedTypes(final Scope scope) {
+	return inferElidedTypes((ParameterizedTypeBinding) this.resolvedType, scope);
+}
+public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding parameterizedType, final Scope scope) {
 	
-	ReferenceBinding genericType = ((ParameterizedTypeBinding) this.resolvedType).genericType();
-	ReferenceBinding enclosingType = this.resolvedType.enclosingType();
+	ReferenceBinding genericType = parameterizedType.genericType();
+	ReferenceBinding enclosingType = parameterizedType.enclosingType();
 	ParameterizedTypeBinding allocationType = scope.environment().createParameterizedType(genericType, genericType.typeVariables(), enclosingType);
 	
 	/* Given the allocation type and the arguments to the constructor, see if we can synthesize a generic static factory
@@ -643,7 +649,7 @@
 		// checking for redundant type parameters must fake a diamond, 
 		// so we infer the same results as we would get with a diamond in source code:
 		this.type.bits |= IsDiamond;
-		inferredTypes = inferElidedTypes(scope);
+		inferredTypes = inferElidedTypes(allocationType, scope);
 	} finally {
 		// reset effects of inference
 		this.type.bits = previousBits;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index 11f6b1c..3eee089 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -4,6 +4,10 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
@@ -286,6 +290,8 @@
 			case 'M' :
 				if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD))
 					return TagBits.AnnotationForMethod;
+				else if (CharOperation.equals(elementName, TypeConstants.UPPER_MODULE))
+					return TagBits.AnnotationForModule;
 				break;
 			case 'P' :
 				if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER))
@@ -634,6 +640,7 @@
 			builder.check(TagBits.AnnotationForPackage, TypeConstants.UPPER_PACKAGE);
 			builder.check(TagBits.AnnotationForTypeParameter, TypeConstants.TYPE_PARAMETER_TARGET);
 			builder.check(TagBits.AnnotationForTypeUse, TypeConstants.TYPE_USE_TARGET);
+			builder.check(TagBits.AnnotationForModule, TypeConstants.UPPER_MODULE);
 			if (builder.hasError()) {
 				repeatableAnnotationType.tagAsHavingDefectiveContainerType();
 				scope.problemReporter().repeatableAnnotationTypeTargetMismatch(culpritNode, repeatableAnnotationType, containerType, builder.toString());
@@ -1133,6 +1140,12 @@
 				if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) {
 					return AnnotationTargetAllowed.YES;
 				}
+				break;
+			case Binding.MODULE:
+				if ((metaTagBits & (TagBits.AnnotationForModule)) != 0) {
+					return AnnotationTargetAllowed.YES;
+				}
+				break;
 		}
 		return AnnotationTargetAllowed.NO;
 	}
@@ -1150,6 +1163,8 @@
 		long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
 		if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
 			// does not specify any target restriction - all locations supported in Java 7 and before are possible
+			// TBD - revisit for modules - as per 9.6.4.1, annotation without target is applicable for module declaration
+			// which is listed as a declaration context, but javac does not allow this
 			if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) {
 				scope.problemReporter().explitAnnotationTargetRequired(annotation);
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index acb079b..e98c07c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann  - Contribution for bug 295551
@@ -30,6 +34,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.parser.NLSTag;
@@ -55,6 +60,7 @@
 	public ImportReference currentPackage;
 	public ImportReference[] imports;
 	public TypeDeclaration[] types;
+	public ModuleDeclaration moduleDeclaration;
 	public int[][] comments;
 
 	public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
@@ -83,6 +89,12 @@
 	int suppressWarningsCount;
 	public int functionalExpressionsCount;
 	public FunctionalExpression[] functionalExpressions;
+	/*
+	 * Name of the module this compilation unit belongs to. Not to be confused with 
+	 * moduleDeclaration, which represents the module this compilation unit may
+	 * define, i.e. if this unit represents module-info.java.
+	 */
+//	public char[] module;
 
 public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) {
 	this.problemReporter = problemReporter;
@@ -201,6 +213,14 @@
 	this.types[0] = declaration; // Assumes the first slot is meant for this type
 }
 
+public void createModuleInfoType(ModuleDeclaration declaration) {
+	TypeDeclaration type = new TypeDeclaration(this.compilationResult);
+	type.name = TypeConstants.MODULE_INFO_NAME;
+	type.modifiers = declaration.modifiers | ClassFileConstants.AccModule;
+	type.javadoc = this.javadoc;
+	this.types[0] = type; // Assumes the first slot is meant for this type
+}
+
 /*
  * Finds the matching type amoung this compilation unit types.
  * Returns null if no type with this name is found.
@@ -421,6 +441,10 @@
 	return CharOperation.equals(getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME);
 }
 
+public boolean isModuleInfo() {
+	return CharOperation.equals(getMainTypeName(), TypeConstants.MODULE_INFO_NAME);
+}
+
 public boolean isSuppressed(CategorizedProblem problem) {
 	if (this.suppressWarningsCount == 0) return false;
 	int irritant = ProblemReporter.getIrritant(problem.getID());
@@ -461,8 +485,9 @@
 			}
 			currentImport.print(0, output).append(";\n"); //$NON-NLS-1$
 		}
-
-	if (this.types != null) {
+	if (this.moduleDeclaration != null) {
+		this.moduleDeclaration.print(indent, output).append("\n"); //$NON-NLS-1$
+	} else if (this.types != null) {
 		for (int i = 0; i < this.types.length; i++) {
 			this.types[i].print(indent, output).append("\n"); //$NON-NLS-1$
 		}
@@ -769,4 +794,12 @@
 		// ignore
 	}
 }
+public char[] module() {
+	if (this.isModuleInfo()) {
+		return this.moduleDeclaration != null ? this.moduleDeclaration.moduleName : ModuleEnvironment.UNNAMED;
+	} else if (this.compilationResult != null && this.compilationResult.compilationUnit != null) {
+		return this.compilationResult.compilationUnit.module();
+	}
+	return ModuleEnvironment.UNNAMED;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java
new file mode 100644
index 0000000..d2fe2ea
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExportsStatement.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+public class ExportsStatement extends PackageVisibilityStatement {
+
+	public ExportsStatement(ImportReference pkgRef) {
+		this(pkgRef, null);
+	}
+	public ExportsStatement(ImportReference pkgRef, ModuleReference[] targets) {
+		super(pkgRef, targets);
+	}
+
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		output.append("exports "); //$NON-NLS-1$
+		super.print(0, output);
+		output.append(";"); //$NON-NLS-1$
+		return output;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index 55cb793..600fbcb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -297,7 +301,8 @@
 			case TypeDeclaration.INTERFACE_DECL :
 				if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8
 						&& (this.modifiers & (ExtraCompilerModifiers.AccSemicolonBody | ClassFileConstants.AccAbstract)) == ExtraCompilerModifiers.AccSemicolonBody) {
-					if ((this.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) != 0) {
+					boolean isPrivateMethod = compilerOptions.sourceLevel >= ClassFileConstants.JDK9 && (this.modifiers & ClassFileConstants.AccPrivate) != 0;
+					if (isPrivateMethod || ((this.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) != 0)) {
 							this.scope.problemReporter().methodNeedBody(this);
 					}
 				}
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
new file mode 100644
index 0000000..7a2ff12
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class ModuleDeclaration extends ASTNode {
+
+	public ExportsStatement[] exports;
+	public RequiresStatement[] requires;
+	public UsesStatement[] uses;
+	public ProvidesStatement[] services;
+	public OpensStatement[] opens;
+	public Annotation[] annotations;
+	public int exportsCount;
+	public int requiresCount;
+	public int usesCount;
+	public int servicesCount;
+	public int opensCount;
+	public ModuleBinding moduleBinding;
+	public int declarationSourceStart;
+	public int declarationSourceEnd;
+	public int bodyStart;
+	public int bodyEnd; // doesn't include the trailing comment if any.
+	public int modifiersSourceStart;
+	//public ClassScope scope;
+	public char[][] tokens;
+	public char[] moduleName;
+	public long[] sourcePositions;
+	public int modifiers = ClassFileConstants.AccDefault;
+
+	public ModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) {
+//		super(compilationResult);
+//		this.compilationResult = compilationResult;
+		this.exportsCount = 0;
+		this.requiresCount = 0;
+		this.tokens = tokens;
+		this.moduleName = CharOperation.concatWith(tokens, '.');
+		this.sourcePositions = positions;
+		this.sourceEnd = (int) (positions[positions.length-1] & 0x00000000FFFFFFFF);
+		this.sourceStart = (int) (positions[0] >>> 32);
+	}
+//	@Override
+//	public void generateCode(ClassFile enclosingClassFile) {
+//		if (this.ignoreFurtherInvestigation) {
+//			return;
+//		}
+//		super.generateCode(enclosingClassFile);
+//	}
+
+	//@Override
+	public void resolve(ClassScope scope) {
+		//
+//		if (this.binding == null) {
+//			this.ignoreFurtherInvestigation = true;
+//			return;
+//		}
+		this.moduleBinding = scope.environment().getModule(this.moduleName);
+		ASTNode.resolveAnnotations(scope.referenceContext.staticInitializerScope, this.annotations, this.moduleBinding);
+		Set<ModuleBinding> requiredModules = new HashSet<ModuleBinding>();
+		for(int i = 0; i < this.requiresCount; i++) {
+			RequiresStatement ref = this.requires[i];
+			if (ref != null && ref.resolve(scope) != null) {
+				if (!requiredModules.add(ref.resolvedBinding)) {
+					scope.problemReporter().duplicateModuleReference(IProblem.DuplicateRequires, ref.module);
+				}
+				Collection<ModuleBinding> deps = ref.resolvedBinding.dependencyGraphCollector().get();
+				if (deps.contains(this.moduleBinding))
+					scope.problemReporter().cyclicModuleDependency(this.moduleBinding, ref.module);
+			}
+		}
+		Set<PackageBinding> exportedPkgs = new HashSet<>();
+		for (int i = 0; i < this.exportsCount; i++) {
+			ExportsStatement ref = this.exports[i];
+ 			if (ref != null && ref.resolve(scope)) {
+				if (!exportedPkgs.add(ref.resolvedPackage)) {
+					scope.problemReporter().invalidPackageReference(IProblem.DuplicateExports, ref);
+				}
+			}
+		}
+		Set<PackageBinding> openedPkgs = new HashSet<>();
+		for (int i = 0; i < this.opensCount; i++) {
+			OpensStatement ref = this.opens[i];
+			if (isOpen()) {
+				scope.problemReporter().invalidOpensStatement(ref, this);
+			} else {
+				if (ref.resolve(scope)) {
+					if (!openedPkgs.add(ref.resolvedPackage)) {
+						scope.problemReporter().invalidPackageReference(IProblem.DuplicateOpens, ref);
+					}
+				}
+			}
+		}
+		Set<TypeBinding> allTypes = new HashSet<TypeBinding>();
+		for(int i = 0; i < this.usesCount; i++) {
+			TypeBinding serviceBinding = this.uses[i].serviceInterface.resolveType(scope);
+			if (serviceBinding != null && serviceBinding.isValidBinding()) {
+				if (!(serviceBinding.isClass() || serviceBinding.isInterface() || serviceBinding.isAnnotationType())) {
+					scope.problemReporter().invalidServiceRef(IProblem.InvalidServiceIntfType, this.uses[i].serviceInterface);
+				}
+				if (!allTypes.add(this.uses[i].serviceInterface.resolvedType)) {
+					scope.problemReporter().duplicateTypeReference(IProblem.DuplicateUses, this.uses[i].serviceInterface);
+				}
+			}
+		}
+		Set<TypeBinding> interfaces = new HashSet<>();
+		for(int i = 0; i < this.servicesCount; i++) {
+			this.services[i].resolve(scope);
+			TypeBinding infBinding = this.services[i].serviceInterface.resolvedType;
+			if (infBinding != null && infBinding.isValidBinding()) {
+				if (!interfaces.add(this.services[i].serviceInterface.resolvedType)) { 
+					scope.problemReporter().duplicateTypeReference(IProblem.DuplicateServices,
+							this.services[i].serviceInterface);
+				}
+			}
+		}
+	}
+
+	
+	public StringBuffer printHeader(int indent, StringBuffer output) {
+		if (this.annotations != null) {
+			for (int i = 0; i < this.annotations.length; i++) {
+				this.annotations[i].print(indent, output);
+				if (i != this.annotations.length - 1)
+					output.append(" "); //$NON-NLS-1$
+			}
+			output.append('\n');
+		}
+		if (isOpen()) {
+			output.append("open "); //$NON-NLS-1$
+		}
+		output.append("module "); //$NON-NLS-1$
+		output.append(CharOperation.charToString(this.moduleName));
+		return output;
+	}
+	private boolean isOpen() {
+		return (this.modifiers & ClassFileConstants.ACC_OPEN) != 0;
+	}
+	public StringBuffer printBody(int indent, StringBuffer output) {
+		output.append(" {"); //$NON-NLS-1$
+		if (this.requires != null) {
+			for(int i = 0; i < this.requiresCount; i++) {
+				output.append('\n');
+				printIndent(indent + 1, output);
+				output.append("requires "); //$NON-NLS-1$
+				this.requires[i].print(0, output);
+				output.append(";"); //$NON-NLS-1$
+			}
+		}
+		if (this.exports != null) {
+			for(int i = 0; i < this.exportsCount; i++) {
+				output.append('\n');
+				this.exports[i].print(indent + 1, output);
+			}
+		}
+		if (this.opens != null) {
+			for(int i = 0; i < this.opensCount; i++) {
+				output.append('\n');
+				this.opens[i].print(indent + 1, output);
+			}
+		}
+		if (this.uses != null) {
+			for(int i = 0; i < this.usesCount; i++) {
+				output.append('\n');
+				this.uses[i].print(indent + 1, output);
+			}
+		}
+		if (this.servicesCount != 0) {
+			for(int i = 0; i < this.servicesCount; i++) {
+				output.append('\n');
+				this.services[i].print(indent + 1, output);
+			}
+		}
+		output.append('\n');
+		return printIndent(indent, output).append('}');
+	}
+
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		//
+		printIndent(indent, output);
+		printHeader(0, output);
+		return printBody(indent, output);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java
new file mode 100644
index 0000000..62114c5
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleReference.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+public class ModuleReference extends ASTNode {
+	public char[][] tokens;
+	public long[] sourcePositions; //each entry is using the code : (start<<32) + end
+	public char[] moduleName;
+	ModuleBinding binding = null;
+
+	public ModuleReference(char[][] tokens, long[] sourcePositions) {
+		this.tokens = tokens;
+		this.sourcePositions = sourcePositions;
+		this.sourceEnd = (int) (sourcePositions[sourcePositions.length - 1] & 0x00000000FFFFFFFF);
+		this.sourceStart = (int) (sourcePositions[0] >>> 32);
+		this.moduleName = CharOperation.concatWith(tokens, '.');
+	}
+	
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		for (int i = 0; i < this.tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(this.tokens[i]);
+		}
+		return output;
+	}
+
+	public ModuleBinding resolve(Scope scope) {
+		if (scope != null && (this.binding = scope.environment().getModule(this.moduleName)) == null) {
+			scope.problemReporter().invalidModule(this);
+		}
+		return this.binding;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java
new file mode 100644
index 0000000..eaff2b1
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleStatement.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+/**
+ * Just a marker class to represent statements that can occur in a module declaration
+ *
+ */
+public abstract class ModuleStatement extends ASTNode {
+
+	public int declarationEnd;
+	public int declarationSourceStart;
+	public int declarationSourceEnd;
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
index 4086a9c..25ea17b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -94,7 +98,7 @@
    Aborts if constraints are violated. Due to various complexities, this check is not conveniently
    implementable in resolve/analyze phases.
 */
-protected void checkEffectiveFinality(LocalVariableBinding localBinding, Scope scope) {
+public void checkEffectiveFinality(VariableBinding localBinding, Scope scope) {
 	if ((this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
 		if (!localBinding.isFinal() && !localBinding.isEffectivelyFinal()) {
 			scope.problemReporter().cannotReferToNonEffectivelyFinalOuterLocal(localBinding, this);
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
new file mode 100644
index 0000000..2ad4e7f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+public class OpensStatement extends PackageVisibilityStatement {
+
+	public OpensStatement(ImportReference pkgRef) {
+		this(pkgRef, null);
+	}
+	public OpensStatement(ImportReference pkgRef, ModuleReference[] targets) {
+		super(pkgRef, targets);
+	}
+	
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		output.append("opens "); //$NON-NLS-1$
+		super.print(0, output);
+		output.append(";"); //$NON-NLS-1$
+		return 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
new file mode 100644
index 0000000..03a9940
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+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.Scope;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+
+public abstract class PackageVisibilityStatement extends ModuleStatement {
+	public ImportReference pkgRef;
+	public ModuleReference[] targets;
+	public char[] pkgName;
+	public PackageBinding resolvedPackage;
+
+	public PackageVisibilityStatement(ImportReference pkgRef, ModuleReference[] targets) {
+		this.pkgRef = pkgRef;
+		this.pkgName = CharOperation.concatWith(this.pkgRef.tokens, '.');
+		this.targets = targets;
+	}
+	public boolean isQualified() {
+		return this.targets != null && this.targets.length > 0;
+	}
+	
+	public ModuleReference[] getTargetedModules() {
+		return this.targets;
+	}
+
+	public boolean resolve(Scope scope) {
+		boolean errorsExist = resolvePackageReference(scope) == null;
+		if (this.isQualified()) {
+			HashtableOfObject modules = new HashtableOfObject(this.targets.length);
+			for (int i = 0; i < this.targets.length; i++) {
+				ModuleReference ref = this.targets[i];
+				if (modules.containsKey(ref.moduleName)) {
+					scope.problemReporter().duplicateModuleReference(IProblem.DuplicateModuleRef, ref);
+					errorsExist = true;
+				} else {
+					ref.resolve(scope.compilationUnitScope());
+					modules.put(ref.moduleName, ref);
+				}
+			}
+		}
+		return !errorsExist;
+	}
+	protected PackageBinding resolvePackageReference(Scope scope) {
+		if (this.resolvedPackage != null)
+			return this.resolvedPackage;
+		ModuleDeclaration exportingModule = scope.compilationUnitScope().referenceContext.moduleDeclaration;
+		ModuleBinding src = exportingModule.moduleBinding;
+		this.resolvedPackage = src != null ? src.getDeclaredPackage(this.pkgRef.tokens) : null;
+		if (this.resolvedPackage == null) {
+			// TODO: need a check for empty package as well
+			scope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, this);
+		}
+		
+		return this.resolvedPackage;
+	}
+
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		this.pkgRef.print(indent, output);
+		if (this.isQualified()) {
+			output.append(" to "); //$NON-NLS-1$
+			for (int i = 0; i < this.targets.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.targets[i].print(0, output);
+			}
+		}
+		return output;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java
new file mode 100644
index 0000000..773b3c9
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ProvidesStatement.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+
+public class ProvidesStatement extends ModuleStatement {
+
+	public TypeReference serviceInterface;
+	public TypeReference[] implementations;
+
+	public boolean resolve(ClassScope scope) {
+		ModuleDeclaration module = scope.compilationUnitScope().referenceContext.moduleDeclaration;
+		ModuleBinding src = module.moduleBinding;
+		TypeBinding infBinding = this.serviceInterface.resolveType(scope);
+		boolean hasErrors = false;
+		if (infBinding == null || !infBinding.isValidBinding()) {
+			return false;
+		}
+		if (!(infBinding.isClass() || infBinding.isInterface() || infBinding.isAnnotationType())) {
+			scope.problemReporter().invalidServiceRef(IProblem.InvalidServiceIntfType, this.serviceInterface);
+		}
+		ReferenceBinding intf = (ReferenceBinding) this.serviceInterface.resolvedType;
+		Set<TypeBinding> impls = new HashSet<>();
+		for (int i = 0; i < this.implementations.length; i++) {
+			ReferenceBinding impl = (ReferenceBinding) this.implementations[i].resolveType(scope);
+			if (impl == null || !impl.isValidBinding() || !impl.canBeSeenBy(scope)) {
+				hasErrors = true;
+				continue;
+			}
+			if (!impls.add(impl)) {
+				scope.problemReporter().duplicateTypeReference(IProblem.DuplicateServices, this.implementations[i]);
+				continue;
+			}
+			int problemId = ProblemReasons.NoError;
+			ModuleBinding declaringModule = impl.module();
+			
+			if (declaringModule != src) {
+				problemId = IProblem.ServiceImplNotDefinedByModule;
+			} else if (!impl.isClass() && !impl.isInterface()) {
+				problemId = IProblem.InvalidServiceImplType;
+			} else if (impl.isNestedType() && !impl.isStatic()) {
+				problemId = IProblem.NestedServiceImpl;
+			} else if (impl.isAbstract()) {
+				problemId = IProblem.AbstractServiceImplementation;
+			} else {
+				MethodBinding provider = impl.getExactMethod(TypeConstants.PROVIDER, Binding.NO_PARAMETERS, scope.compilationUnitScope());
+				if (provider != null && (!provider.isValidBinding() || !(provider.isPublic() && provider.isStatic()))) {
+					provider = null;
+				}
+				TypeBinding implType = impl;
+				if (provider != null) {
+					implType = provider.returnType;
+					if (!implType.canBeSeenBy(scope)) {
+						//
+						scope.problemReporter().invalidType(this.implementations[i], new ProblemReferenceBinding(
+								CharOperation.NO_CHAR_CHAR, (ReferenceBinding) implType, ProblemReasons.NotVisible));
+						hasErrors = true;
+					}
+				} else {
+					MethodBinding defaultConstructor = impl.getExactConstructor(Binding.NO_PARAMETERS);
+					if (defaultConstructor == null || !defaultConstructor.isValidBinding()) {
+						problemId = IProblem.ProviderMethodOrConstructorRequiredForServiceImpl;
+					} else if (!defaultConstructor.isPublic()) {
+						problemId = IProblem.ServiceImplDefaultConstructorNotPublic;
+					}
+				}
+				if (implType.findSuperTypeOriginatingFrom(intf) == null) {
+					scope.problemReporter().typeMismatchError(implType, intf, this.implementations[i], null);
+					hasErrors = true;
+				}
+			}
+			if (problemId != ProblemReasons.NoError) {
+				scope.problemReporter().invalidServiceRef(problemId, this.implementations[i]);
+				hasErrors = true;
+			}
+		}
+		return hasErrors;
+	}
+
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		output.append("provides "); //$NON-NLS-1$
+		this.serviceInterface.print(0, output);
+		//output.append(" "); //$NON-NLS-1$
+		//printIndent(indent + 1, output);
+		output.append(" with "); //$NON-NLS-1$
+		for (int i = 0; i < this.implementations.length; i++) {
+			this.implementations[i].print(0, output);
+			if (i < this.implementations.length - 1)
+				output.append(", "); //$NON-NLS-1$
+		}
+		output.append(";"); //$NON-NLS-1$
+		return output;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 6a377df..06605ac 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -36,6 +36,8 @@
 
 import static org.eclipse.jdt.internal.compiler.ast.ExpressionContext.INVOCATION_CONTEXT;
 
+import java.util.Arrays;
+
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
@@ -48,6 +50,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier;
+import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18;
 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -59,8 +62,10 @@
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
@@ -305,7 +310,7 @@
 		}
 		return result;
 	}
-
+	
 	private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope) {
 		// Propagate the type checking to the arguments, and checks if the constructor is defined.
 		// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
@@ -480,8 +485,10 @@
 				}
 			} else {
 				if (isDiamond) {
-					scope.problemReporter().diamondNotWithAnoymousClasses(this.type);
-					return null;
+					if (sourceLevel < ClassFileConstants.JDK9) {
+						scope.problemReporter().diamondNotWithAnoymousClasses(this.type);
+						return null;
+					}
 				}	
 				ReferenceBinding superType = (ReferenceBinding) receiverType;
 				if (superType.isTypeVariable()) {
@@ -492,61 +499,7 @@
 					scope.problemReporter().cannotInstantiate(this.type, superType);
 					return this.resolvedType = superType;
 				}
-				// anonymous type scenario
-				// an anonymous class inherits from java.lang.Object when declared "after" an interface
-				ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType;
-				// insert anonymous type in scope
-				scope.addAnonymousType(this.anonymousType, superType);
-				this.anonymousType.resolve(scope);
-
-				// find anonymous super constructor
-				this.resolvedType = this.anonymousType.binding; // 1.2 change
-				if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) {
-					return null; // stop secondary errors
-				}
-				MethodBinding inheritedBinding = findConstructorBinding(scope, this, anonymousSuperclass, this.argumentTypes);
-
-				if (!inheritedBinding.isValidBinding()) {
-					if (inheritedBinding.declaringClass == null) {
-						inheritedBinding.declaringClass = anonymousSuperclass;
-					}
-					if (this.type != null && !this.type.resolvedType.isValidBinding()) {
-						// problem already got signaled on type reference, do not report secondary problem
-						return null;
-					}
-					scope.problemReporter().invalidConstructor(this, inheritedBinding);
-					return this.resolvedType;
-				}
-				if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) {
-					scope.problemReporter().missingTypeInConstructor(this, inheritedBinding);
-				}
-				if (this.enclosingInstance != null) {
-					ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType();
-					if (targetEnclosing == null) {
-						scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType);
-						return this.resolvedType;
-					} else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
-						scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance, null);
-						return this.resolvedType;
-					}
-					this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
-				}
-				if (this.arguments != null) {
-					if (checkInvocationArguments(scope, null, anonymousSuperclass, inheritedBinding, this.arguments, this.argumentTypes, this.argsContainCast, this)) {
-						this.bits |= ASTNode.Unchecked;
-					}
-				}
-				if (this.typeArguments != null && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
-					scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(inheritedBinding, this.genericTypeArguments, this.typeArguments);
-				}
-				// Update the anonymous inner class : superclass, interface
-				LookupEnvironment environment=scope.environment();
-				if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
-					ImplicitNullAnnotationVerifier.ensureNullnessIsKnown(inheritedBinding, scope);
-				}
-
-				this.binding = this.anonymousType.createDefaultConstructorWithBinding(inheritedBinding, 	(this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null);
-				return this.resolvedType;
+				this.resolvedType = receiverType;
 			}
 		} else {
 			if (this.enclosingInstance != null) {
@@ -554,8 +507,9 @@
 				this.resolvedType = receiverType = this.type.resolvedType;
 			}
 		}
+		MethodBinding constructorBinding = null;
 		if (isDiamond) {
-			this.binding = inferConstructorOfElidedParameterizedType(scope);
+			this.binding = constructorBinding = inferConstructorOfElidedParameterizedType(scope);
 			if (this.binding == null || !this.binding.isValidBinding()) {
 				scope.problemReporter().cannotInferElidedTypes(this);
 				return this.resolvedType = null;
@@ -564,50 +518,134 @@
 				return new PolyTypeBinding(this);
 			}
 			this.resolvedType = this.type.resolvedType = receiverType = this.binding.declaringClass;
+			if (this.anonymousType != null) {
+				constructorBinding = getAnonymousConstructorBinding((ReferenceBinding) receiverType, scope);
+				if (constructorBinding == null)
+					return null;
+				this.resolvedType = this.anonymousType.binding;
+				// Check that inferred type is valid
+				if (!validate((ParameterizedTypeBinding) receiverType, scope)) {
+					return this.resolvedType;
+				}
+			}
 			resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope);
 		} else {
-			this.binding = findConstructorBinding(scope, this, (ReferenceBinding) receiverType, this.argumentTypes);
-		}
-
-		if (this.binding.isValidBinding()) {	
-			if (isMethodUseDeprecated(this.binding, scope, true)) {
-				scope.problemReporter().deprecatedMethod(this.binding, this);
+			if (this.anonymousType != null) {
+				constructorBinding = getAnonymousConstructorBinding((ReferenceBinding) receiverType, scope);
+				if (constructorBinding == null)
+					return null;
+				this.resolvedType = this.anonymousType.binding;
+			} else {
+				this.binding = constructorBinding = findConstructorBinding(scope, this, (ReferenceBinding) receiverType, this.argumentTypes);
 			}
-			if (checkInvocationArguments(scope, null, receiverType, this.binding, this.arguments, this.argumentTypes, this.argsContainCast, this)) {
+		}
+		ReferenceBinding receiver = (ReferenceBinding) receiverType;
+		ReferenceBinding superType = receiver.isInterface() ? scope.getJavaLangObject() : receiver;
+		if (constructorBinding.isValidBinding()) {
+			if (isMethodUseDeprecated(constructorBinding, scope, true)) {
+				scope.problemReporter().deprecatedMethod(constructorBinding, this);
+			}
+			if (checkInvocationArguments(scope, null, superType, constructorBinding, this.arguments,
+					this.argumentTypes, this.argsContainCast, this)) {
 				this.bits |= ASTNode.Unchecked;
 			}
-			if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
-				scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments);
+			if (this.typeArguments != null && constructorBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
+				scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(constructorBinding,
+						this.genericTypeArguments, this.typeArguments);
 			}
 		} else {
-			if (this.binding.declaringClass == null) {
-				this.binding.declaringClass = (ReferenceBinding) receiverType;
+			if (constructorBinding.declaringClass == null) {
+				constructorBinding.declaringClass = superType;
 			}
 			if (this.type != null && !this.type.resolvedType.isValidBinding()) {
 				// problem already got signaled on type reference, do not report secondary problem
 				return null;
 			}
-			scope.problemReporter().invalidConstructor(this, this.binding);
+			scope.problemReporter().invalidConstructor(this, constructorBinding);
+			return this.resolvedType;
+		}
+		if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0) {
+			scope.problemReporter().missingTypeInConstructor(this, constructorBinding);
+		}
+		if (this.enclosingInstance != null) {
+			ReferenceBinding targetEnclosing = constructorBinding.declaringClass.enclosingType();
+			if (targetEnclosing == null) {
+				scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, receiver);
+				return this.resolvedType;
+			} else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
+				scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance, null);
+				return this.resolvedType;
+			}
+			this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
+		}
+		if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments() && 
+				(this.anonymousType == null || sourceLevel >= ClassFileConstants.JDK9)) {
+			checkTypeArgumentRedundancy((ParameterizedTypeBinding) receiverType, scope);
+		}
+		if (this.anonymousType != null) {
+			// anonymous type scenario
+			// Update the anonymous inner class : superclass, interface
+			LookupEnvironment environment=scope.environment();
+			if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+				ImplicitNullAnnotationVerifier.ensureNullnessIsKnown(constructorBinding, scope);
+			}
+			this.binding = this.anonymousType.createDefaultConstructorWithBinding(constructorBinding, (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null);
+			return this.resolvedType;
+		} else {
 			return this.resolvedType = receiverType;
 		}
-		if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
-			scope.problemReporter().missingTypeInConstructor(this, this.binding);
-		}
-		if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) {
-			checkTypeArgumentRedundancy((ParameterizedTypeBinding)receiverType, scope);
-		}
-		// The enclosing instance must be compatible with the innermost enclosing type
-		ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
-		if (TypeBinding.notEquals(expectedType, enclosingInstanceType)) // must call before computeConversion() and typeMismatchError()
-			scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType);
-		if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) {
-			this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType);
-			return this.resolvedType = receiverType;
-		}
-		scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null);
-		return this.resolvedType = receiverType;
 	}
 
+	private boolean validate(final ParameterizedTypeBinding allocationType, final Scope scope) {
+		class ValidityInspector extends TypeBindingVisitor {
+			private boolean noErrors;
+
+			public ValidityInspector() {
+				this.noErrors = true;
+			}
+
+			public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) {
+				Arrays.sort(intersectionTypeBinding18.intersectingTypes, (t1, t2) -> t1.id - t2.id);
+				scope.problemReporter().anonymousDiamondWithNonDenotableTypeArguments(QualifiedAllocationExpression.this.type, allocationType);
+				return this.noErrors = false;  // stop traversal
+			}
+			public boolean visit(TypeVariableBinding typeVariable) {
+				if (typeVariable.isCapture()) {
+					scope.problemReporter().anonymousDiamondWithNonDenotableTypeArguments(QualifiedAllocationExpression.this.type, allocationType);
+					return this.noErrors = false;  // stop traversal
+				}
+				return true; // continue traversal
+			}
+			public boolean visit(ReferenceBinding ref) {
+				if (!ref.canBeSeenBy(scope)) {
+					scope.problemReporter().invalidType(QualifiedAllocationExpression.this.anonymousType, new ProblemReferenceBinding(ref.compoundName, ref, ProblemReasons.NotVisible));
+					return this.noErrors = false;
+				}
+				return true;
+			}
+			public boolean isValid() {
+				TypeBindingVisitor.visit(this, allocationType);
+				return this.noErrors;
+			}
+		}
+		
+		return new ValidityInspector().isValid();
+	}
+	private MethodBinding getAnonymousConstructorBinding(ReferenceBinding receiverType, BlockScope scope) {
+		ReferenceBinding superType = receiverType;
+		// an anonymous class inherits from java.lang.Object when declared "after" an interface
+		ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType;
+		// insert anonymous type in scope
+		scope.addAnonymousType(this.anonymousType, superType);
+		this.anonymousType.resolve(scope);
+
+		// find anonymous super constructor
+		this.resolvedType = this.anonymousType.binding; // 1.2 change
+		if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) {
+			return null; // stop secondary errors
+		}
+		return findConstructorBinding(scope, this, anonymousSuperclass, this.argumentTypes);
+	}
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
 			if (this.enclosingInstance != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java
new file mode 100644
index 0000000..23ea4b8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RequiresStatement.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+public class RequiresStatement extends ModuleStatement {
+
+	public ModuleReference module;
+	public ModuleBinding resolvedBinding;
+	public int modifiers = ClassFileConstants.AccDefault;
+	public int modifiersSourceStart;
+
+	public RequiresStatement(ModuleReference module) {
+		this.module = module;
+	}
+	public boolean isTransitive() {
+		return (this.modifiers & ClassFileConstants.ACC_TRANSITIVE) != 0;
+	}
+	public boolean isStatic() {
+		return (this.modifiers & ClassFileConstants.ACC_STATIC_PHASE) != 0;
+	}
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		if (isTransitive())
+			output.append("transitive "); //$NON-NLS-1$
+		if (isStatic())
+			output.append("static "); //$NON-NLS-1$
+		this.module.print(indent, output);
+		return output;
+	}
+	public ModuleBinding resolve(Scope scope) {
+		if (this.resolvedBinding != null)
+			return this.resolvedBinding;
+		return this.resolvedBinding = this.module.resolve(scope);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index 7282b48..94b0d79 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -47,9 +51,7 @@
 	static final char[] SECRET_CAUGHT_THROWABLE_VARIABLE_NAME = " caughtThrowable".toCharArray(); //$NON-NLS-1$;
 	static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$
 
-	private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0];
-	public LocalDeclaration[] resources = NO_RESOURCES;
-
+	public Statement[] resources = new Statement[0];
 	public Block tryBlock;
 	public Block[] catchBlocks;
 
@@ -146,17 +148,29 @@
 
 		FlowInfo tryInfo = flowInfo.copy();
 		for (int i = 0; i < resourcesLength; i++) {
-			final LocalDeclaration resource = this.resources[i];
+			final Statement resource = this.resources[i];			
 			tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo);
 			this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo);
-			LocalVariableBinding resourceBinding = resource.binding;
-			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
-			if (resourceBinding.closeTracker != null) {
-				// this was false alarm, we don't need to track the resource
-				resourceBinding.closeTracker.withdraw();
-				resourceBinding.closeTracker = null;
+			TypeBinding resolvedType = null;
+			LocalVariableBinding localVariableBinding = null;
+			if (resource instanceof LocalDeclaration) {
+				localVariableBinding = ((LocalDeclaration) resource).binding;
+				resolvedType = localVariableBinding.type;
+			} else { //expression
+				if (resource instanceof NameReference && ((NameReference) resource).binding instanceof LocalVariableBinding) {
+					localVariableBinding = (LocalVariableBinding) ((NameReference) resource).binding;
+				}
+				resolvedType = ((Expression) resource).resolvedType;
 			}
-			MethodBinding closeMethod = findCloseMethod(resource, resourceBinding);
+			if (localVariableBinding != null) {
+				localVariableBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
+				if (localVariableBinding.closeTracker != null) {
+					// this was false alarm, we don't need to track the resource
+					localVariableBinding.closeTracker.withdraw();
+					localVariableBinding.closeTracker = null;
+				}
+			}
+			MethodBinding closeMethod = findCloseMethod(resource, resolvedType);
 			if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) {
 				ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions;
 				for (int j = 0, length = thrownExceptions.length; j < length; j++) {
@@ -175,7 +189,8 @@
 			// to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since
 			// it is used to add or remove assigned resources during code gen
 			for (int i = 0; i < resourcesLength; i++) {
-				tryInfo.resetAssignmentInfo(this.resources[i].binding);
+				if (this.resources[i] instanceof LocalDeclaration)
+				tryInfo.resetAssignmentInfo(((LocalDeclaration) this.resources[i]).binding);
 			}
 		}
 		// check unreachable catch blocks
@@ -260,17 +275,29 @@
 
 		FlowInfo tryInfo = flowInfo.copy();
 		for (int i = 0; i < resourcesLength; i++) {
-			final LocalDeclaration resource = this.resources[i];
+			final Statement resource = this.resources[i];
 			tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo);
 			this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo);
-			LocalVariableBinding resourceBinding = resource.binding;
-			resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
-			if (resourceBinding.closeTracker != null) {
-				// this was false alarm, we don't need to track the resource
-				resourceBinding.closeTracker.withdraw();
-				// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
+			TypeBinding resolvedType = null;
+			LocalVariableBinding localVariableBinding = null;
+			if (resource instanceof LocalDeclaration) {
+				localVariableBinding = ((LocalDeclaration) this.resources[i]).binding;
+				resolvedType = localVariableBinding.type;
+			} else { // Expression
+				if (resource instanceof NameReference && ((NameReference) resource).binding instanceof LocalVariableBinding) {
+					localVariableBinding = (LocalVariableBinding)((NameReference) resource).binding;
+				}
+				resolvedType = ((Expression) resource).resolvedType;
 			}
-			MethodBinding closeMethod = findCloseMethod(resource, resourceBinding);
+			if (localVariableBinding != null) {
+				localVariableBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
+				if (localVariableBinding.closeTracker != null) {
+					// this was false alarm, we don't need to track the resource
+					localVariableBinding.closeTracker.withdraw();
+					// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
+				}
+			}
+			MethodBinding closeMethod = findCloseMethod(resource, resolvedType);
 			if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) {
 				ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions;
 				for (int j = 0, length = thrownExceptions.length; j < length; j++) {
@@ -289,7 +316,8 @@
 			// to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since
 			// it is used to add or remove assigned resources during code gen
 			for (int i = 0; i < resourcesLength; i++) {
-				tryInfo.resetAssignmentInfo(this.resources[i].binding);
+				if (this.resources[i] instanceof LocalDeclaration)
+				tryInfo.resetAssignmentInfo(((LocalDeclaration)this.resources[i]).binding);
 			}
 		}
 		// check unreachable catch blocks
@@ -346,10 +374,9 @@
 		}
 	}
 }
-private MethodBinding findCloseMethod(final LocalDeclaration resource, LocalVariableBinding resourceBinding) {
+private MethodBinding findCloseMethod(final ASTNode resource, TypeBinding type) {
 	MethodBinding closeMethod = null;
-	TypeBinding type = resourceBinding.type;
-	if (type != null && type.isValidBinding()) {
+	if (type != null && type.isValidBinding() && type instanceof ReferenceBinding) {
 		ReferenceBinding binding = (ReferenceBinding) type;
 		closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter
 		if(closeMethod == null) {
@@ -396,7 +423,7 @@
 	"(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index])
 	ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]."
 	*/
-	if (this.tryBlock.statements == null && this.resources == NO_RESOURCES) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350579
+	if (this.tryBlock.statements == null && this.resources == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350579
 		catchInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
 	}
 	return catchInfo;
@@ -515,7 +542,18 @@
 				this.resourceExceptionLabels[i] = new ExceptionLabel(codeStream, null);
 				this.resourceExceptionLabels[i].placeStart();
 				if (i < resourceCount) {
-					this.resources[i].generateCode(this.scope, codeStream); // Initialize resources ...
+					Statement stmt = this.resources[i];
+					if (stmt instanceof NameReference) {
+						NameReference ref = (NameReference) stmt;
+						ref.bits |= ASTNode.IsCapturedOuterLocal; // TODO: selective flagging if ref.binding is not one of earlier inlined LVBs.
+						VariableBinding binding = (VariableBinding) ref.binding; // Only LVB expected here.
+						ref.checkEffectiveFinality(binding, this.scope);
+					} else if (stmt instanceof FieldReference) {
+						FieldReference fieldReference = (FieldReference) stmt;
+						if (!fieldReference.binding.isFinal())
+							this.scope.problemReporter().cannotReferToNonFinalField(fieldReference.binding, fieldReference);
+					}
+					stmt.generateCode(this.scope, codeStream); // Initialize resources ...
 				}
 			}
 		}
@@ -525,7 +563,7 @@
 				BranchLabel exitLabel = new BranchLabel(codeStream);
 				this.resourceExceptionLabels[i].placeEnd(); // outer handler if any is the one that should catch exceptions out of close()
 				
-				LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null;
+				Statement stmt = i > 0 ? this.resources[i - 1] : null;
 				if ((this.bits & ASTNode.IsTryBlockExiting) == 0) {
 					// inline resource closure
 					if (i > 0) {
@@ -537,10 +575,7 @@
 							codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
 							codeStream.addDefinitelyAssignedVariables(currentScope, this.postTryInitStateIndex);
 						}
-						codeStream.load(localVariable);
-						codeStream.ifnull(exitLabel);
-						codeStream.load(localVariable);
-						codeStream.invokeAutoCloseableClose(localVariable.type);
+						generateCodeSnippet(stmt, codeStream, exitLabel, false /* record */);
 						codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd);
 					}
 					codeStream.goto_(exitLabel); // skip over the catch block.
@@ -582,13 +617,7 @@
 				if (i > 0) {
 					// inline resource close here rather than bracketing the current catch block with a try region.
 					BranchLabel postCloseLabel = new BranchLabel(codeStream);
-					int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785			
-					codeStream.load(localVariable);
-					codeStream.ifnull(postCloseLabel);
-					codeStream.load(localVariable);
-					codeStream.invokeAutoCloseableClose(localVariable.type);
-					codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd);
-					codeStream.removeVariable(localVariable);
+					generateCodeSnippet(stmt, codeStream, postCloseLabel, true /* record */, i, codeStream.position);						
 					postCloseLabel.place();
 				}
 				codeStream.load(this.primaryExceptionVariable);
@@ -843,6 +872,64 @@
 	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
+private void generateCodeSnippet(Statement statement, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int... values) {
+	
+	int i = -1; 
+	int invokeCloseStartPc = -1;
+	if (record) {
+		i = values[0];
+		invokeCloseStartPc = values[1];
+	}
+	if (statement instanceof LocalDeclaration)
+		generateCodeSnippet((LocalDeclaration)statement, codeStream, postCloseLabel, record, i, invokeCloseStartPc);
+	else if (statement instanceof Reference)
+		generateCodeSnippet((Reference)statement, codeStream, postCloseLabel, record, i, invokeCloseStartPc);
+	// else abort
+}
+
+private void generateCodeSnippet(Reference reference, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int i, int invokeCloseStartPc) {
+	reference.generateCode(this.scope, codeStream, true);
+	codeStream.ifnull(postCloseLabel);
+	reference.generateCode(this.scope, codeStream, true);
+	codeStream.invokeAutoCloseableClose(reference.resolvedType);
+	if (!record) return;
+	codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd);
+	isDuplicateResourceReference(i);
+}
+private void generateCodeSnippet(LocalDeclaration localDeclaration, CodeStream codeStream, BranchLabel postCloseLabel, boolean record, int i, int invokeCloseStartPc) {
+	LocalVariableBinding variableBinding = localDeclaration.binding;
+	codeStream.load(variableBinding);
+	codeStream.ifnull(postCloseLabel);
+	codeStream.load(variableBinding);
+	codeStream.invokeAutoCloseableClose(variableBinding.type);
+	if (!record) return;
+	codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd);
+	if (!isDuplicateResourceReference(i)) // do not remove duplicate variable now
+		codeStream.removeVariable(variableBinding);
+}
+
+private boolean isDuplicateResourceReference(int index) {
+	int len = this.resources.length;
+	if (index < len && this.resources[index] instanceof Reference) {
+		Reference ref = (Reference) this.resources[index];
+		Binding refBinding =  ref instanceof NameReference ? ((NameReference) ref).binding :
+			ref instanceof FieldReference ? ((FieldReference) ref).binding : null;
+		if (refBinding == null) return false;
+		
+		//TODO: For field accesses in the form of a.b.c and b.c - could there be a non-trivial dup - to check?
+		for (int i = 0; i < index; i++) {
+			Statement stmt = this.resources[i];
+			Binding b = stmt instanceof LocalDeclaration ? ((LocalDeclaration) stmt).binding : 
+				stmt instanceof NameReference ? ((NameReference) stmt).binding :
+						stmt instanceof FieldReference ? ((FieldReference) stmt).binding : null;
+			if (b == refBinding) {
+				this.scope.problemReporter().duplicateResourceReference(ref);
+				return true;
+			}
+		}
+	}
+	return false;
+}
 
 /**
  * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding)
@@ -854,13 +941,9 @@
 		for (int i = resourceCount; i > 0; --i) {
 			// Disarm the handlers and take care of resource closure.
 			this.resourceExceptionLabels[i].placeEnd();
-			LocalVariableBinding localVariable = this.resources[i-1].binding;
 			BranchLabel exitLabel = new BranchLabel(codeStream);
 			int invokeCloseStartPc = codeStream.position; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=343785
-			codeStream.load(localVariable);
-			codeStream.ifnull(exitLabel);
-			codeStream.load(localVariable);
-			codeStream.invokeAutoCloseableClose(localVariable.type);
+			generateCodeSnippet(this.resources[i - 1], codeStream, exitLabel, false);
 			codeStream.recordPositionsFrom(invokeCloseStartPc, this.tryBlock.sourceEnd);
 			exitLabel.place();
 		}
@@ -954,7 +1037,12 @@
 	int length = this.resources.length;
 	printIndent(indent, output).append("try" + (length == 0 ? "\n" : " (")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	for (int i = 0; i < length; i++) {
-		this.resources[i].printAsExpression(0, output);
+		Statement stmt = this.resources[i];
+		if (stmt instanceof LocalDeclaration) {
+			((LocalDeclaration) stmt).printAsExpression(0, output);
+		} else if (stmt instanceof Reference) {
+			((Reference) stmt).printExpression(0, output);
+		} else continue;
 		if (i != length - 1) {
 			output.append(";\n"); //$NON-NLS-1$
 			printIndent(indent + 2, output);
@@ -1002,19 +1090,34 @@
 	}
 	for (int i = 0; i < resourceCount; i++) {
 		this.resources[i].resolve(resourceManagementScope);
-		LocalVariableBinding localVariableBinding = this.resources[i].binding;
-		if (localVariableBinding != null && localVariableBinding.isValidBinding()) {
-			localVariableBinding.modifiers |= ClassFileConstants.AccFinal;
-			localVariableBinding.tagBits |= TagBits.IsResource;
-			TypeBinding resourceType = localVariableBinding.type;
-			if (resourceType instanceof ReferenceBinding) {
-				if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) {
-					upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type);
+		if (this.resources[i] instanceof LocalDeclaration) {
+			LocalDeclaration node = (LocalDeclaration)this.resources[i];
+			LocalVariableBinding localVariableBinding = node.binding;
+			if (localVariableBinding != null && localVariableBinding.isValidBinding()) {
+				localVariableBinding.modifiers |= ClassFileConstants.AccFinal;
+				localVariableBinding.tagBits |= TagBits.IsResource;
+				TypeBinding resourceType = localVariableBinding.type;
+				if (resourceType instanceof ReferenceBinding) {
+					if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) {
+						upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node.type);
+						localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
+					}
+				} else if (resourceType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=349862, avoid secondary error in problematic null case
+					upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node.type);
 					localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
 				}
+			}
+		} else { // expression
+			Expression node = (Expression) this.resources[i];
+			TypeBinding resourceType = node.resolvedType;
+			if (resourceType instanceof ReferenceBinding) {
+				if (resourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangAutoCloseable, false /*AutoCloseable is not a class*/) == null && resourceType.isValidBinding()) {
+					upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node);
+					((Expression) this.resources[i]).resolvedType = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
+				}
 			} else if (resourceType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=349862, avoid secondary error in problematic null case
-				upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, this.resources[i].type);
-				localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
+				upperScope.problemReporter().resourceHasToImplementAutoCloseable(resourceType, node);
+				((Expression) this.resources[i]).resolvedType = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
 			}
 		}
 	}
@@ -1110,9 +1213,9 @@
 }
 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	if (visitor.visit(this, blockScope)) {
-		LocalDeclaration[] localDeclarations = this.resources;
-		for (int i = 0, max = localDeclarations.length; i < max; i++) {
-			localDeclarations[i].traverse(visitor, this.scope);
+		Statement[] statements = this.resources;
+		for (int i = 0, max = statements.length; i < max; i++) {
+			statements[i].traverse(visitor, this.scope);
 		}
 		this.tryBlock.traverse(visitor, this.scope);
 		if (this.catchArguments != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 30b3d11..a5c5bf0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -35,6 +39,7 @@
 	public static final int INTERFACE_DECL = 2;
 	public static final int ENUM_DECL = 3;
 	public static final int ANNOTATION_TYPE_DECL = 4;
+	public static final int MODULE_DECL = 5;
 
 	public int modifiers = ClassFileConstants.AccDefault;
 	public int modifiersSourceStart;
@@ -747,13 +752,15 @@
 }
 
 public final static int kind(int flags) {
-	switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum)) {
+	switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum|ClassFileConstants.AccModule)) {
 		case ClassFileConstants.AccInterface :
 			return TypeDeclaration.INTERFACE_DECL;
 		case ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation :
 			return TypeDeclaration.ANNOTATION_TYPE_DECL;
 		case ClassFileConstants.AccEnum :
 			return TypeDeclaration.ENUM_DECL;
+		case ClassFileConstants.AccModule:
+			return TypeDeclaration.MODULE_DECL;
 		default :
 			return TypeDeclaration.CLASS_DECL;
 	}
@@ -1305,6 +1312,11 @@
  */
 public void resolve(CompilationUnitScope upperScope) {
 	// top level : scope are already created
+	if (isModuleInfo()) {
+		ModuleDeclaration module = upperScope.referenceContext.moduleDeclaration;
+		module.resolve(this.scope);
+		return;
+	}
 	resolve();
 	updateMaxFieldCount();
 }
@@ -1508,6 +1520,9 @@
 public boolean isPackageInfo() {
 	return CharOperation.equals(this.name,  TypeConstants.PACKAGE_INFO_NAME);
 }
+public boolean isModuleInfo() {
+	return CharOperation.equals(this.name,  TypeConstants.MODULE_INFO_NAME);
+}
 /**
  * Returns whether the type is a secondary one or not.
  */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java
new file mode 100644
index 0000000..d061d4c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UsesStatement.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+public class UsesStatement extends ModuleStatement {
+
+	public TypeReference serviceInterface;
+
+	public UsesStatement(TypeReference serviceInterface) {
+		this.serviceInterface = serviceInterface;
+	}
+	@Override
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		output.append("uses "); //$NON-NLS-1$
+		this.serviceInterface.print(0, output);
+		output.append(";"); //$NON-NLS-1$
+		return output;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
index 3538098..fd258d4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
@@ -289,7 +289,6 @@
 			case 22:
 				if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_DEPRECATED)) {
 					this.standardAnnotationTagBits |= TagBits.AnnotationDeprecated;
-					return currentOffset;
 				}
 				break;
 			case 23:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 1bc40eb..47c3ed1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contributions for
@@ -40,6 +44,7 @@
 	int AccSynthetic    = 0x1000;
 	int AccAnnotation   = 0x2000;
 	int AccEnum         = 0x4000;
+	int AccModule		= 0x8000;
 
 	/**
 	 * From classfile version 52 (compliance 1.8 up), meaning that a formal parameter is mandated
@@ -47,6 +52,13 @@
 	 */
 	int AccMandated     = 0x8000;
 
+	/**
+	 * Flags in module declaration - since java9
+	 */
+	int ACC_OPEN			= 0x0020;
+	int ACC_TRANSITIVE 		= 0x0020;
+	int ACC_STATIC_PHASE	= 0x0040;
+	int ACC_SYNTHETIC 		= 0x1000;
 	
 	/**
 	 * Other VM flags.
@@ -73,6 +85,8 @@
 	int MethodHandleTag = 15;
 	int MethodTypeTag = 16;
 	int InvokeDynamicTag = 18;
+	int ModuleTag = 19;
+	int PackageTag = 20;
 
 	int ConstantMethodRefFixedSize = 5;
 	int ConstantClassFixedSize = 3;
@@ -88,6 +102,8 @@
 	int ConstantMethodHandleFixedSize = 4;
 	int ConstantMethodTypeFixedSize = 3;
 	int ConstantInvokeDynamicFixedSize = 5;
+	int ConstantModuleFixedSize = 3;
+	int ConstantPackageFixedSize = 3;
 
 	// JVMS 4.4.8
 	int MethodHandleRefKindGetField = 1;
@@ -108,7 +124,7 @@
 	int MAJOR_VERSION_1_6 = 50;
 	int MAJOR_VERSION_1_7 = 51;
 	int MAJOR_VERSION_1_8 = 52;
-	int MAJOR_VERSION_1_9 = 53; // This might change
+	int MAJOR_VERSION_9 = 53;
 
 	int MINOR_VERSION_0 = 0;
 	int MINOR_VERSION_1 = 1;
@@ -116,7 +132,7 @@
 	int MINOR_VERSION_3 = 3;
 	int MINOR_VERSION_4 = 4;
 
-	// JDK 1.1 -> 1.9, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
+	// JDK 1.1 -> 9, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
 	// 16 unsigned bits for major, then 16 bits for minor
 	long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3
 	long JDK1_2 =  ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0;
@@ -126,7 +142,7 @@
 	long JDK1_6 = ((long)ClassFileConstants.MAJOR_VERSION_1_6 << 16) + ClassFileConstants.MINOR_VERSION_0;
 	long JDK1_7 = ((long)ClassFileConstants.MAJOR_VERSION_1_7 << 16) + ClassFileConstants.MINOR_VERSION_0;
 	long JDK1_8 = ((long)ClassFileConstants.MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0;
-	long JDK1_9 = ((long)ClassFileConstants.MAJOR_VERSION_1_9 << 16) + ClassFileConstants.MINOR_VERSION_0;
+	long JDK9 = ((long)ClassFileConstants.MAJOR_VERSION_9 << 16) + ClassFileConstants.MINOR_VERSION_0;
 
 	/*
 	 * cldc1.1 is 45.3, but we modify it to be different from JDK1_1.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index ff1db76..c7bc52e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -20,6 +24,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Optional;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants;
@@ -31,12 +37,14 @@
 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.IModule;
 import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ClassFileReader extends ClassFileStruct implements IBinaryType {
@@ -49,6 +57,8 @@
 	private AnnotationInfo[] annotations;
 	private TypeAnnotationInfo[] typeAnnotations;
 	private FieldInfo[] fields;
+	private IModule moduleDeclaration;
+	public char[] moduleName;
 	private int fieldsCount;
 
 	// initialized in case the .class file is a nested type
@@ -117,6 +127,29 @@
 		return read(zip, filename, false);
 }
 
+public static ClassFileReader readFromJimage(
+		File jrt,
+		String filename)
+		throws ClassFormatException, java.io.IOException {
+
+		return readFromModules(jrt, filename, Optional.empty());
+	}
+public static ClassFileReader readFromJrt(
+		File jrt,
+		String filename,
+		IModule module)
+
+		throws ClassFormatException, java.io.IOException {
+		return JRTUtil.getClassfile(jrt, filename, module);
+	}
+public static ClassFileReader readFromModules(
+		File jrt,
+		String filename,
+		Optional<Collection<char[]>> moduleNames)
+
+		throws ClassFormatException, java.io.IOException {
+		return JRTUtil.getClassfile(jrt, filename, moduleNames);
+}
 public static ClassFileReader read(
 	java.util.zip.ZipFile zip,
 	String filename,
@@ -141,6 +174,11 @@
 	return read(new File(fileName), fullyInitialize);
 }
 
+public ClassFileReader(byte classFileBytes[], char[] fileName, char[] mod) throws ClassFormatException {
+	this(classFileBytes, fileName, false);
+	this.moduleName = mod;
+}
+
 /**
  * @param classFileBytes Actual bytes of a .class file
  * @param fileName	Actual name of the file that contains the bytes, can be null
@@ -237,6 +275,14 @@
 					this.constantPoolOffsets[i] = readOffset;
 					readOffset += ClassFileConstants.ConstantInvokeDynamicFixedSize;
 					break;
+				case ClassFileConstants.ModuleTag:
+					this.constantPoolOffsets[i] = readOffset;
+					readOffset += ClassFileConstants.ConstantModuleFixedSize;
+					break;
+				case ClassFileConstants.PackageTag:
+					this.constantPoolOffsets[i] = readOffset;
+					readOffset += ClassFileConstants.ConstantPackageFixedSize;
+					break;
 			}
 		}
 		// Read and validate access flags
@@ -245,7 +291,9 @@
 
 		// Read the classname, use exception handlers to catch bad format
 		this.classNameIndex = u2At(readOffset);
-		this.className = getConstantClassNameAt(this.classNameIndex);
+		if (this.classNameIndex != 0) {
+			this.className = getConstantClassNameAt(this.classNameIndex);
+		}
 		readOffset += 2;
 
 		// Read the superclass name, can be null for java.lang.Object
@@ -393,6 +441,9 @@
 								missingTypeOffset += 2;
 							}
 						}
+					} else if (CharOperation.equals(attributeName, AttributeNamesConstants.ModuleName)) {
+						this.moduleDeclaration = ModuleInfo.createModule(this.className, this.reference, this.constantPoolOffsets, readOffset);
+						this.moduleName = this.moduleDeclaration.name();
 					}
 			}
 			readOffset += (6 + u4At(readOffset + 2));
@@ -562,6 +613,21 @@
 public IBinaryField[] getFields() {
 	return this.fields;
 }
+/**
+ * @see IBinaryType#getModule()
+ */
+public char[] getModule() {
+	return this.moduleName;
+}
+/**
+ * Returns the module declaration that this class file represents. This will be 
+ * null for non module-info class files.
+ * 
+ * @return the module declaration this represents
+ */
+public IModule getModuleDeclaration() {
+	return this.moduleDeclaration;
+}
 
 /**
  * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java
index f379a7e..eea6557 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationDecorator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 Google, Inc. and others.
+ * Copyright (c) 2016, 2017 Google, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -287,4 +287,10 @@
 		}
 		return ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
 	}
+
+	@Override
+	public char[] getModule() {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java
new file mode 100644
index 0000000..61a0328
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ModuleInfo.java
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.classfmt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+
+public class ModuleInfo extends ClassFileStruct implements IModule {
+	protected int flags;
+	protected int requiresCount;
+	protected int exportsCount;
+	protected int usesCount;
+	protected int providesCount;
+	protected int opensCount;
+	protected char[] name;
+	protected char[] version;
+	protected ModuleReferenceInfo[] requires;
+	protected PackageExportInfo[] exports;
+	protected PackageExportInfo[] opens;
+	char[][] uses;
+	IModule.IService[] provides;
+
+	public int requiresCount() {
+		return this.requiresCount;
+	}
+	public int exportsCount() {
+		return this.exportsCount;
+	}
+	public int usesCount() {
+		return this.usesCount;
+	}
+	public int providesCount() {
+		return this.providesCount;
+	}
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+	public void setName(char[] name) {
+		this.name = name;
+	}
+	@Override
+	public IModule.IModuleReference[] requires() {
+		return this.requires;
+	}
+	@Override
+	public IModule.IPackageExport[] exports() {
+		return this.exports;
+	}
+	@Override
+	public char[][] uses() {
+		return this.uses;
+	}
+	@Override
+	public IService[] provides() {
+		return this.provides;
+	}
+	@Override
+	public IModule.IPackageExport[] opens() {
+		return this.opens;
+	}
+	public void addReads(char[] modName) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n));
+		};
+		if (shouldAdd.test(modName)) {
+			int len = this.requires.length;
+			this.requires = Arrays.copyOf(this.requires, len);
+			ModuleReferenceInfo info = this.requires[len] = new ModuleReferenceInfo();
+			info.refName = modName;
+		}		
+	}
+	public void addExports(IPackageExport[] toAdd) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.exports).map(ref -> ref.packageName).noneMatch(n -> CharOperation.equals(m, n));
+		};
+		Collection<PackageExportInfo> merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd)
+				.filter(e -> shouldAdd.test(e.name()))
+				.map(e -> {
+					PackageExportInfo exp = new PackageExportInfo();
+					exp.packageName = e.name();
+					exp.exportedTo = e.targets();
+					return exp;
+				}))
+			.collect(
+				ArrayList::new,
+				ArrayList::add,
+				ArrayList::addAll);
+		this.exports = merged.toArray(new PackageExportInfo[merged.size()]);
+	}
+	/**
+	 * @param classFileBytes byte[]
+	 * @param offsets int[]
+	 * @param offset int
+	 */
+	protected ModuleInfo (byte classFileBytes[], int offsets[], int offset) {
+		super(classFileBytes, offsets, offset);
+	}
+
+	public static ModuleInfo createModule(char[] className, byte classFileBytes[], int offsets[], int offset) {
+
+		int readOffset = offset;
+//		module.name = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1)); // returns 'Module' 
+		int moduleOffset = readOffset + 6;
+		int utf8Offset;
+		ModuleInfo module = new ModuleInfo(classFileBytes, offsets, 0);
+		int name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+		utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+		module.name = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+		CharOperation.replace(module.name, '/', '.');
+		moduleOffset += 2;
+		module.flags = module.u2At(moduleOffset);
+		moduleOffset += 2;
+		int version_index = module.u2At(moduleOffset);
+		if (version_index > 0) {
+			utf8Offset = module.constantPoolOffsets[version_index];
+			module.version = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+		}
+		moduleOffset += 2;
+
+		utf8Offset = module.constantPoolOffsets[module.u2At(readOffset)];
+		int count = module.u2At(moduleOffset);
+		module.requiresCount = count;
+		module.requires = new ModuleReferenceInfo[count];
+		moduleOffset += 2;
+		for (int i = 0; i < count; i++) {
+			name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+			utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+			char[] requiresNames = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			module.requires[i] = module.new ModuleReferenceInfo();
+			CharOperation.replace(requiresNames, '/', '.');
+			module.requires[i].refName = requiresNames;
+			moduleOffset += 2;
+			int modifiers = module.u2At(moduleOffset);
+			module.requires[i].modifiers = modifiers;
+			module.requires[i].isTransitive = (ClassFileConstants.ACC_TRANSITIVE & modifiers) != 0; // Access modifier
+			moduleOffset += 2;
+			version_index = module.u2At(moduleOffset);
+			if (version_index > 0) {
+				utf8Offset = module.constantPoolOffsets[version_index];
+				module.requires[i].required_version = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			}
+			moduleOffset += 2;
+		}
+		count = module.u2At(moduleOffset);
+		moduleOffset += 2;
+		module.exportsCount = count;
+		module.exports = new PackageExportInfo[count];
+		for (int i = 0; i < count; i++) {
+			name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+			utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+			char[] exported = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			CharOperation.replace(exported, '/', '.');
+			PackageExportInfo pack = module.new PackageExportInfo();
+			module.exports[i] = pack;
+			pack.packageName = exported;
+			moduleOffset += 2;
+			pack.modifiers = module.u2At(moduleOffset);
+			moduleOffset += 2;
+			int exportedtoCount = module.u2At(moduleOffset);
+			moduleOffset += 2;
+			if (exportedtoCount > 0) {
+				pack.exportedTo = new char[exportedtoCount][];
+				pack.exportedToCount = exportedtoCount;
+				for(int k = 0; k < exportedtoCount; k++) {
+					name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+					utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+					char[] exportedToName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+					CharOperation.replace(exportedToName, '/', '.');
+					pack.exportedTo[k] = exportedToName;
+					moduleOffset += 2;
+				}
+			}
+		}
+		count = module.u2At(moduleOffset);
+		moduleOffset += 2;
+		module.opensCount = count;
+		module.opens = new PackageExportInfo[count];
+		for (int i = 0; i < count; i++) {
+			name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+			utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+			char[] exported = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			CharOperation.replace(exported, '/', '.');
+			PackageExportInfo pack = module.new PackageExportInfo();
+			module.opens[i] = pack;
+			pack.packageName = exported;
+			moduleOffset += 2;
+			pack.modifiers = module.u2At(moduleOffset);
+			moduleOffset += 2;
+			int exportedtoCount = module.u2At(moduleOffset);
+			moduleOffset += 2;
+			if (exportedtoCount > 0) {
+				pack.exportedTo = new char[exportedtoCount][];
+				pack.exportedToCount = exportedtoCount;
+				for(int k = 0; k < exportedtoCount; k++) {
+					name_index = module.constantPoolOffsets[module.u2At(moduleOffset)];
+					utf8Offset = module.constantPoolOffsets[module.u2At(name_index + 1)];
+					char[] exportedToName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+					CharOperation.replace(exportedToName, '/', '.');
+					pack.exportedTo[k] = exportedToName;
+					moduleOffset += 2;
+				}
+			}
+		}
+		count = module.u2At(moduleOffset);
+		moduleOffset += 2;
+		module.usesCount = count;
+		module.uses = new char[count][];
+		for (int i = 0; i < count; i++) {
+			int classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)];
+			utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)];
+			char[] inf = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			CharOperation.replace(inf, '/', '.');
+			module.uses[i] = inf;
+			moduleOffset += 2;
+		}
+		count = module.u2At(moduleOffset);
+		moduleOffset += 2;
+		module.providesCount = count;
+		module.provides = new ServiceInfo[count];
+		for (int i = 0; i < count; i++) {
+			int classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)];
+			utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)];
+			char[] inf = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+			CharOperation.replace(inf, '/', '.');
+			ServiceInfo service = module.new ServiceInfo();
+			module.provides[i] = service;
+			service.serviceName = inf;
+			moduleOffset += 2;
+			int implCount = module.u2At(moduleOffset);
+			moduleOffset += 2;
+			service.with = new char[implCount][];
+			if (implCount > 0) {
+				service.with = new char[implCount][];
+				for(int k = 0; k < implCount; k++) {
+					classIndex = module.constantPoolOffsets[module.u2At(moduleOffset)];
+					utf8Offset = module.constantPoolOffsets[module.u2At(classIndex + 1)];
+					char[] implName = module.utf8At(utf8Offset + 3, module.u2At(utf8Offset + 1));
+					CharOperation.replace(implName, '/', '.');
+					service.with[k] = implName;
+					moduleOffset += 2;
+				}
+			}
+		}
+		return module;
+	}
+	class ModuleReferenceInfo implements IModule.IModuleReference {
+		char[] refName;
+		boolean isTransitive = false;
+		int modifiers;
+		char[] required_version;
+		@Override
+		public char[] name() {
+			return this.refName;
+		}
+		@Override
+		public boolean isTransitive() {
+			return this.isTransitive;
+		}
+		public boolean equals(Object o) {
+			if (this == o) 
+				return true;
+			if (!(o instanceof IModule.IModuleReference))
+				return false;
+			IModule.IModuleReference mod = (IModule.IModuleReference) o;
+			if (this.modifiers != mod.getModifiers())
+				return false;
+			return CharOperation.equals(this.refName, mod.name(), false);
+		}
+		@Override
+		public int hashCode() {
+			return this.refName.hashCode();
+		}
+		@Override
+		public int getModifiers() {
+			return this.modifiers;
+		}
+	}
+	class PackageExportInfo implements IModule.IPackageExport {
+		char[] packageName;
+		char[][] exportedTo;
+		int exportedToCount;
+		int modifiers;
+		@Override
+		public char[] name() {
+			return this.packageName;
+		}
+
+		@Override
+		public char[][] targets() {
+			return this.exportedTo;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			toStringContent(buffer);
+			return buffer.toString();
+		}
+		protected void toStringContent(StringBuffer buffer) {
+			buffer.append(this.packageName);
+			if (this.exportedToCount > 0) {
+				buffer.append(" to "); //$NON-NLS-1$
+				for(int i = 0; i < this.exportedToCount; i++) {
+					buffer.append(this.exportedTo[i]);
+					buffer.append(',').append(' ');
+				}
+			}
+			buffer.append(';').append('\n');
+		}
+	}
+	class ServiceInfo implements IModule.IService {
+		char[] serviceName;
+		char[][] with;
+		@Override
+		public char[] name() {
+			return this.serviceName;
+		}
+
+		@Override
+		public char[][] with() {
+			return this.with;
+		}
+	}
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (!(o instanceof IModule))
+			return false;
+		IModule mod = (IModule) o;
+		if (!CharOperation.equals(this.name, mod.name()))
+			return false;
+		return Arrays.equals(this.requires, mod.requires());
+	}
+	@Override
+	public int hashCode() {
+		int result = 17;
+		int c = this.name.hashCode();
+		result = 31 * result + c;
+		c =  Arrays.hashCode(this.requires);
+		result = 31 * result + c;
+		return result;
+	}
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(getClass().getName());
+		toStringContent(buffer);
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer) {
+		buffer.append("\nmodule "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append('\n');
+		if (this.requiresCount > 0) {
+			for(int i = 0; i < this.requiresCount; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (this.requires[i].isTransitive) {
+					buffer.append(" public "); //$NON-NLS-1$
+				}
+				buffer.append(this.requires[i].refName);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.exportsCount > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.exportsCount; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(this.exports[i].toString());
+			}
+		}
+		buffer.append('\n').append('}').toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
index a6fa626..993dc8e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contributions for
@@ -28,6 +32,7 @@
 	final char[] SignatureName = "Signature".toCharArray(); //$NON-NLS-1$
 	final char[] LocalVariableTypeTableName = "LocalVariableTypeTable".toCharArray(); //$NON-NLS-1$
 	final char[] EnclosingMethodName = "EnclosingMethod".toCharArray(); //$NON-NLS-1$
+	final char[] ModuleName = "Module".toCharArray(); //$NON-NLS-1$
 	final char[] AnnotationDefaultName = "AnnotationDefault".toCharArray(); //$NON-NLS-1$
 	final char[] RuntimeInvisibleAnnotationsName = "RuntimeInvisibleAnnotations".toCharArray(); //$NON-NLS-1$
 	final char[] RuntimeVisibleAnnotationsName = "RuntimeVisibleAnnotations".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 2cc8154..d56c3f0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contributions for
@@ -51,6 +55,8 @@
 	protected CharArrayCache stringCache;
 	protected HashtableOfObject methodsAndFieldsCache;
 	protected CharArrayCache classCache;
+	protected CharArrayCache moduleCache;
+	protected CharArrayCache packageCache;
 	protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods;
 	public byte[] poolContent;
 	public int currentIndex = 1;
@@ -306,6 +312,8 @@
 		this.stringCache = new CharArrayCache(STRING_INITIAL_SIZE);
 		this.methodsAndFieldsCache = new HashtableOfObject(METHODS_AND_FIELDS_INITIAL_SIZE);
 		this.classCache = new CharArrayCache(CLASS_INITIAL_SIZE);
+		this.moduleCache = new CharArrayCache(5);
+		this.packageCache = new CharArrayCache(5);
 		this.nameAndTypeCacheForFieldsAndMethods = new HashtableOfObject(NAMEANDTYPE_INITIAL_SIZE);
 		this.offsets = new int[5];
 		initialize(classFile);
@@ -671,6 +679,64 @@
 		}
 		return index;
 	}
+	public int literalIndexForModule(final char[] moduleName) {
+		int index;
+		if ((index = this.moduleCache.putIfAbsent(moduleName, this.currentIndex)) < 0) {
+			// The entry doesn't exit yet
+			this.currentIndex++;
+			if ((index = -index) > 0xFFFF){
+				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+			}
+			// Write the tag first
+			int length = this.offsets.length;
+			if (length <= index) {
+				// resize
+				System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length);
+			}
+			this.offsets[index] = this.currentOffset;
+			writeU1(ModuleTag);
+			// Then the string index
+			int stringIndexOffset = this.currentOffset;
+			if (this.currentOffset + 2 >= this.poolContent.length) {
+				resizePoolContents(2);
+			}
+			this.currentOffset+=2;
+
+			final int stringIndex = literalIndex(moduleName);
+			this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8);
+			this.poolContent[stringIndexOffset] = (byte) stringIndex;
+		}
+		return index;
+	}
+	public int literalIndexForPackage(final char[] packageName) {
+		int index;
+		if ((index = this.packageCache.putIfAbsent(packageName, this.currentIndex)) < 0) {
+			// The entry doesn't exit yet
+			this.currentIndex++;
+			if ((index = -index) > 0xFFFF){
+				this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+			}
+			// Write the tag first
+			int length = this.offsets.length;
+			if (length <= index) {
+				// resize
+				System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length);
+			}
+			this.offsets[index] = this.currentOffset;
+			writeU1(PackageTag);
+			// Then the string index
+			int stringIndexOffset = this.currentOffset;
+			if (this.currentOffset + 2 >= this.poolContent.length) {
+				resizePoolContents(2);
+			}
+			this.currentOffset+=2;
+
+			final int stringIndex = literalIndex(packageName);
+			this.poolContent[stringIndexOffset++] = (byte) (stringIndex >> 8);
+			this.poolContent[stringIndexOffset] = (byte) stringIndex;
+		}
+		return index;
+	}
 	public int literalIndexForType(final char[] constantPoolName) {
 		int index;
 		if ((index = this.classCache.putIfAbsent(constantPoolName, this.currentIndex)) < 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
index dfd3ea1..7e03eed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -59,6 +63,12 @@
 
 IBinaryField[] getFields();
 /**
+ * Answer the module to which this type belongs.
+ *
+ * @return the module
+ */
+char[] getModule();
+/**
  * Answer the receiver's ClassSignature, which describes the type parameters,
  * super class, and super interfaces as specified in section "4.7.9.1 Signatures"
  * of the Java SE 8 VM spec.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
index bbe34a2..51d1343 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -12,6 +16,13 @@
 
 /**
  * This interface denotes a compilation unit, providing its name and content.
+ * 
+ * <p>
+ * Note: This internal interface has been implemented illegally by the
+ * org.apache.jasper.glassfish bundle from Orbit, see
+ * <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=500211">bug 500211</a>.
+ * Avoid changing the API or supply default methods to avoid breaking the Eclipse Help system.
+ * </p>
  */
 public interface ICompilationUnit extends IDependent {
 /**
@@ -39,5 +50,15 @@
 * Answer if optional problems should be ignored for this compilation unit.
 * Implementors should return <code>false</code> if there is no preference.
 */
-boolean ignoreOptionalProblems();
+default boolean ignoreOptionalProblems() {
+	return false;
+}
+/**
+ * Returns the name of the module that this compilation unit belongs to.
+ *
+ * @return the name of the module as a char array.
+ */
+default char[] module() {
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java
new file mode 100644
index 0000000..a0dd12c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModule.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
+public interface IModule {
+
+	public static IModuleReference[] NO_MODULE_REFS = new IModuleReference[0];
+	public static IPackageExport[] NO_EXPORTS = new IPackageExport[0];
+	public static char[][] NO_USES = new char[0][];
+	public static IService[] NO_PROVIDES = new IService[0];
+	public static IModule[] NO_MODULES = new IModule[0];
+	public static IPackageExport[] NO_OPENS = new IPackageExport[0];
+
+	public char[] name();
+
+	public IModuleReference[] requires();
+
+	public IPackageExport[] exports();
+
+	public char[][] uses();
+
+	public IService[] provides();
+
+	/*
+	 * the opens package statement is very similar to package export statement, hence
+	 * the same internal models are being used here.
+	 */
+	public IPackageExport[] opens();
+
+	public interface IModuleReference {
+		public char[] name();
+		public default boolean isTransitive() {
+			return (getModifiers() & ClassFileConstants.ACC_TRANSITIVE) != 0;
+		}
+		public int getModifiers();
+		public default boolean isStatic() {
+			return (getModifiers() & ClassFileConstants.ACC_STATIC_PHASE) != 0;
+		}
+	}
+
+	public interface IPackageExport {
+		public char[] name();
+		public char[][] targets();
+		public default boolean isQualified() {
+			char[][] targets = targets();
+			return targets != null && targets.length > 0;
+		}
+	}
+
+	public interface IService {
+		public char[] name();
+		char[][] with();
+	}
+	
+	public default void addReads(char[] modName) {
+		// do nothing, would throwing an exception be better?
+	}
+	
+	public default void addExports(IPackageExport[] exports) {
+		// do nothing, would throwing an exception be better?
+	}
+
+	public default boolean isAutomatic() {
+		return false;
+	}
+}
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
new file mode 100644
index 0000000..56e5bd3
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+/**
+ * A module aware name environment
+ *
+ */
+public interface IModuleAwareNameEnvironment extends INameEnvironment {
+	default NameEnvironmentAnswer findType(char[][] compoundTypeName) {
+		return findType(compoundTypeName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+	default NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+		return findType(typeName, packageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+	default boolean isPackage(char[][] parentPackageName, char[] packageName) {
+		return isPackage(parentPackageName, packageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+
+	NameEnvironmentAnswer findType(char[][] compoundTypeName, IModuleContext moduleContext);
+	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext moduleContext);
+	boolean isPackage(char[][] parentPackageName, char[] packageName, IModuleContext moduleContext);
+	IModule getModule(char[] moduleName);
+	IModuleEnvironment getModuleEnvironmentFor(char[] moduleName);
+	IModule[] getAllAutomaticModules();
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleContext.java
new file mode 100644
index 0000000..5c2cbdd
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleContext.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import java.util.stream.Stream;
+
+/**
+ * The context in which a module aware environment will perform lookup.
+ * Basically a supplier of {@link IModuleEnvironment}s to be included
+ * during a lookup operation
+ *
+ */
+public interface IModuleContext {
+	/**
+	 * A special context to represent the unnamed module context
+	 * 
+	 */
+	IModuleContext UNNAMED_MODULE_CONTEXT = () -> {
+		return Stream.empty();
+	};
+	/**
+	 * Return the environments that are included in this context
+	 * 
+	 */
+	public Stream<IModuleEnvironment> getEnvironment();
+	
+	/**
+	 * Include the other module context in this context
+	 * 
+	 * @param other
+	 * 
+	 * @return A joint context that represents both the module contexts
+	 */
+	default IModuleContext include(IModuleContext other) {
+		return () -> Stream.concat(getEnvironment(), other.getEnvironment());
+	}
+	/**
+	 * Include all the other contexts in this context
+	 * 
+	 * @param other
+	 * 
+	 * @return A joint context that represents all the module contexts
+	 */
+	default IModuleContext includeAll(Stream<IModuleContext> other) {
+		return () -> Stream.concat(getEnvironment(), other.flatMap(c -> c.getEnvironment()));
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleEnvironment.java
new file mode 100644
index 0000000..c27309e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleEnvironment.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+/**
+ * The module environment provides a callback API that the compiler
+ * can use to look up types, compilation units, and packages in the 
+ * context of one or modules. A lookup environment for a module can
+ * be obtained from the IModulePathEntry that contributes the module
+ * 
+ * @see IModulePathEntry#getLookupEnvironmentFor(IModule)
+ */
+public interface IModuleEnvironment {
+	static String MODULE_INFO = "module-info"; //$NON-NLS-1$
+	static String MODULE_INFO_JAVA = "module-info.java"; //$NON-NLS-1$
+	static String MODULE_INFO_CLASS = "module-info.class"; //$NON-NLS-1$
+
+	/**
+	 * A way to lookup types in a module
+	 * 
+	 * @return A TypeLookup that can look up types in a module
+	 */
+	ITypeLookup typeLookup();
+	
+	/**
+	 * A way to lookup packages in a module
+	 * 
+	 * @return A PackageLookup that can look up packages in a module
+	 */
+	IPackageLookup packageLookup();
+
+	/**
+	  * Answer whether qualifiedName is the name of a known package in the
+	  * module this environment represents
+	  * The default package is always assumed to exist. 
+	  * 
+	  * @param qualifiedName
+	 */
+	default boolean isPackage(String qualifiedName) {
+		return packageLookup().isPackage(qualifiedName);
+	}
+	
+	/**
+	 * Find class with the given type name and qualified package name from the module this environment represents
+	 *
+	 * @param typeName
+	 * @param qualifiedPackageName
+	 * @param qualifiedBinaryFileName
+	 * @param asBinaryOnly
+	 * 
+	 * @return a NameEnvironmentAnswer or null if no such type exists
+	 */
+//	default NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+//		return typeLookup().findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
+//	}
+//	default NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, char[] mod) {
+//		if (servesModule(mod))
+//			return typeLookup().findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
+//		return null;
+//	}
+
+}
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
new file mode 100644
index 0000000..1e9372f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/**
+ * Represents an entry on the module path of a project. Could be a single module or a collection of
+ * modules (like a jimage or an exploded module directory structure)
+ *
+ */
+public interface IModulePathEntry {
+
+	/**
+	 * Get the module that this entry contributes. May be null, for instance when this entry does not
+	 * represent a single module
+	 * 
+	 * @return The module that this entry contributes or null
+	 */
+	default IModule getModule() {
+		return null;
+	}
+	
+	/**
+	 * Get the module named name from this entry. May be null
+	 * 
+	 * @param name - The name of the module to look up
+	 * 
+	 * @return The module named name or null
+	 */
+	default IModule getModule(char[] name) {
+		IModule mod = getModule();
+		if (mod != null && CharOperation.equals(name, mod.name()))
+			return mod;
+		return null;
+	}
+
+	/**
+	 * Indicates whether this entry knows the module named name and can answer queries regarding the module
+	 * 
+	 * @param name The name of the module
+	 * 
+	 * @return True if this entry knows the module, false otherwise
+	 */
+	default boolean servesModule(char[] name) {
+		return getModule(name) != null;
+	}
+	/**
+	 * Return the look up environment for this entry. Should be used when one needs to
+	 * look up types/packages in all the modules contributed by this entry
+	 * 
+	 */
+	IModuleEnvironment getLookupEnvironment();
+	/**
+	 * Return the lookup environment for the given module
+	 * 
+	 * @param module
+	 * 
+	 * @return The look up environment for the module, or null if this entry
+	 * does not know any such module
+	 */
+	IModuleEnvironment getLookupEnvironmentFor(IModule module);
+	/**
+	 * Specifies whether this entry represents an automatic module.
+	 * 
+	 * @return true if this is an automatic module, false otherwise
+	 */
+	public default boolean isAutomaticModule() {
+		return false;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java
new file mode 100644
index 0000000..7c6d5ed
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleEntry.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+/**
+ * Represents a module path entry that represents a collection of modules
+ * like a jimage or an exploded module directory structure
+ *
+ */
+public interface IMultiModuleEntry extends IModulePathEntry {
+
+	/**
+	 * Get the module named name that this entry contributes to the module path 
+	 */
+
+	IModule getModule(char[] name);
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModulePackageLookup.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModulePackageLookup.java
new file mode 100644
index 0000000..35c1953
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModulePackageLookup.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import java.util.Optional;
+
+public interface IMultiModulePackageLookup extends IPackageLookup {
+
+	/**
+	 * Answers whether qualifiedPackageName is the name of a known package in the module named module
+	 * The unnamed package is always assumed to exist
+	 * 
+	 * @param qualifiedName
+	 * 
+	 * @throws NullPointerException if module is null
+	 */
+	default boolean isPackage(String qualifiedName) {
+		return isPackage(qualifiedName, Optional.empty());
+	}
+	/**
+	 * Answers whether qualifiedPackageName is the name of a known package in the module named module
+	 * The unnamed package is always assumed to exist
+	 * 
+	 * @param qualifiedName
+	 * @param module
+	 * 
+	 * @throws NullPointerException if module is null
+	 */
+	default boolean isPackage(String qualifiedName, char[] module) {
+		return isPackage(qualifiedName, Optional.of(module));
+	}
+	/**
+	 * Answers whether qualifiedPackageName is the name of a known package in the module named moduleName
+	 * The unnamed package is always assumed to exist
+	 * 
+	 * @param qualifiedName
+	 * @param moduleName
+	 */
+	boolean isPackage(String qualifiedName, Optional<char[]> moduleName);
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleTypeLookup.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleTypeLookup.java
new file mode 100644
index 0000000..840c115
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IMultiModuleTypeLookup.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+
+/**
+ * Functional interface for looking up types in multiple modules
+ * 
+ */
+public interface IMultiModuleTypeLookup extends ITypeLookup {
+	default NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false, Optional.empty());
+	}
+	default public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly, Optional.empty());
+	}
+	default NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, char[] module) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false, Optional.of(Collections.singletonList(module)));
+	}
+	/**
+	 * Find the class named typeName with binary file name qualifiedBinaryFileName in the package whose full name is qualifiedPackageName
+	 * 
+	 * @param typeName
+	 * @param qualifiedPackageName
+	 * @param qualifiedBinaryFileName
+	 * @param asBinaryOnly Look for only binary files
+	 * @param modules The modules to search in.
+	 * 
+	 * @return NameEnvironmentAnswer if found, otherwise null
+	 * 
+	 * @throws NullPointerException the collection is null or contains nulls
+	 */
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, Optional<Collection<char[]>> modules);
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java
index 9a7a2e0..971f93a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -15,57 +19,64 @@
  * can use to look up types, compilation units, and packages in the
  * current environment. The name environment is passed to the compiler
  * on creation.
+ * 
+ * <p>
+ * Note: This internal interface has been implemented illegally by the
+ * org.apache.jasper.glassfish bundle from Orbit, see
+ * <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=500211">bug 500211</a>.
+ * Avoid changing the API or supply default methods to avoid breaking the Eclipse Help system.
+ * </p>
  */
 public interface INameEnvironment {
-/**
- * Find a type with the given compound name.
- * Answer the binary form of the type if it is known to be consistent.
- * Otherwise, answer the compilation unit which defines the type
- * or null if the type does not exist.
- * Types in the default package are specified as {{typeName}}.
- *
- * It is unknown whether the package containing the type actually exists.
- *
- * NOTE: This method can be used to find a member type using its
- * internal name A$B, but the source file for A is answered if the binary
- * file is inconsistent.
- */
+	/**
+	 * Find a type with the given compound name.
+	 * Answer the binary form of the type if it is known to be consistent.
+	 * Otherwise, answer the compilation unit which defines the type
+	 * or null if the type does not exist.
+	 * Types in the default package are specified as {{typeName}}.
+	 *
+	 * It is unknown whether the package containing the type actually exists.
+	 *
+	 * NOTE: This method can be used to find a member type using its
+	 * internal name A$B, but the source file for A is answered if the binary
+	 * file is inconsistent.
+	 */
 
-NameEnvironmentAnswer findType(char[][] compoundTypeName);
-/**
- * Find a type named <typeName> in the package <packageName>.
- * Answer the binary form of the type if it is known to be consistent.
- * Otherwise, answer the compilation unit which defines the type
- * or null if the type does not exist.
- * The default package is indicated by char[0][].
- *
- * It is known that the package containing the type exists.
- *
- * NOTE: This method can be used to find a member type using its
- * internal name A$B, but the source file for A is answered if the binary
- * file is inconsistent.
- */
+	NameEnvironmentAnswer findType(char[][] compoundTypeName);
+	/**
+	 * Find a type named <typeName> in the package <packageName>.
+	 * Answer the binary form of the type if it is known to be consistent.
+	 * Otherwise, answer the compilation unit which defines the type
+	 * or null if the type does not exist.
+	 * The default package is indicated by char[0][].
+	 *
+	 * It is known that the package containing the type exists.
+	 *
+	 * NOTE: This method can be used to find a member type using its
+	 * internal name A$B, but the source file for A is answered if the binary
+	 * file is inconsistent.
+	 */
 
-NameEnvironmentAnswer findType(char[] typeName, char[][] packageName);
-/**
- * Answer whether packageName is the name of a known subpackage inside
- * the package parentPackageName. A top level package is found relative to null.
- * The default package is always assumed to exist.
- *
- * For example:
- *      isPackage({{java}, {awt}}, {event});
- *      isPackage(null, {java});
- */
+	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName);
+	/**
+	 * Answer whether packageName is the name of a known subpackage inside
+	 * the package parentPackageName. A top level package is found relative to null.
+	 * The default package is always assumed to exist.
+	 *
+	 * For example:
+	 *      isPackage({{java}, {awt}}, {event});
+	 *      isPackage(null, {java});
+	 */
 
-boolean isPackage(char[][] parentPackageName, char[] packageName);
+	boolean isPackage(char[][] parentPackageName, char[] packageName);
 
-/**
- * This method cleans the environment. It is responsible for releasing the memory
- * and freeing resources. Passed that point, the name environment is no longer usable.
- *
- * A name environment can have a long life cycle, therefore it is the responsibility of
- * the code which created it to decide when it is a good time to clean it up.
- */
-void cleanup();
+	/**
+	 * This method cleans the environment. It is responsible for releasing the memory
+	 * and freeing resources. Passed that point, the name environment is no longer usable.
+	 *
+	 * A name environment can have a long life cycle, therefore it is the responsibility of
+	 * the code which created it to decide when it is a good time to clean it up.
+	 */
+	void cleanup();
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java
index 4dc4972..a77eb7b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/INameEnvironmentExtension.java
@@ -43,6 +43,10 @@
 	 * @param searchWithSecondaryTypes flag to switch on/off the search for secondary types
 	 * @return {@link NameEnvironmentAnswer}
 	 */
-	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes);
+	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, IModuleContext moduleContext);
+	default NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) {
+		return findType(typeName, packageName, searchWithSecondaryTypes, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+	
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IPackageLookup.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IPackageLookup.java
new file mode 100644
index 0000000..2037d2f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IPackageLookup.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+/**
+ * Functional interface for looking up packages
+ * 
+ */
+public interface IPackageLookup {
+
+	IPackageLookup Dummy = qualifiedPackageName -> false;
+
+	/**
+	 * Answer whether qualifiedPackageName is the name of a known package
+	 * The default package is always assumed to exist.
+	 *
+	 */
+	boolean isPackage(String qualifiedPackageName);
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ITypeLookup.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ITypeLookup.java
new file mode 100644
index 0000000..7700d2c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ITypeLookup.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import java.util.function.BiFunction;
+
+/**
+ * Functional interface for looking up types
+ * 
+ */
+public interface ITypeLookup {
+
+	ITypeLookup Dummy = (typeName, qualifiedPackageName, qualifiedBinaryFileName,binaryOnly) -> null;
+
+	/**
+	 * Find the class named typeName with binary file name qualifiedBinaryFileName in the package whose full name is qualifiedPackageName
+	 * 
+	 * @param typeName
+	 * @param qualifiedPackageName
+	 * @param qualifiedBinaryFileName
+	 * 
+	 * @return NameEnvironmentAnswer if found, otherwise null
+	 */
+	default public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+		return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+	}
+
+	/**
+	 * Find the class named typeName with binary file name qualifiedBinaryFileName in the package whose full name is qualifiedPackageName
+	 * 
+	 * @param typeName
+	 * @param qualifiedPackageName
+	 * @param qualifiedBinaryFileName
+	 * @param asBinaryOnly Look for only binary files
+	 * 
+	 * @return NameEnvironmentAnswer if found, otherwise null
+	 */
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly);
+
+	BiFunction<NameEnvironmentAnswer, ITypeLookup, ITypeLookup> orBetter = (suggested, other) -> {
+		return (typeName, qualifiedPackageName, qualifiedBinaryFileName,binaryOnly) -> {
+			NameEnvironmentAnswer answer = other.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, binaryOnly);
+			if (answer != null) {
+				if (!answer.ignoreIfBetter()) {
+					if (answer.isBetter(suggested))
+						return answer;
+				} else if (answer.isBetter(suggested))
+					// remember suggestion and keep looking
+					return answer;
+			}
+			return suggested;
+		};
+	};
+
+	/**
+	 * Returns a composed TypeLookup that represents a short circuiting TypeLookup which returns
+	 * the better answer between this TypeLookup and other
+	 *   
+	 * @param other
+	 * @return Chained TypeLookup
+	 */
+	default ITypeLookup chain(ITypeLookup other) {
+		NameEnvironmentAnswer suggestedAnswer = null;
+		return (typeName, qualifiedPackageName, qualifiedBinaryFileName, binaryOnly) -> {
+			NameEnvironmentAnswer answer = findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, binaryOnly);
+			if (answer != null) {
+				if (!answer.ignoreIfBetter()) {
+					if (answer.isBetter(suggestedAnswer))
+						return answer;
+				} else if (answer.isBetter(suggestedAnswer))
+					// remember suggestion and keep looking
+					return orBetter.apply(answer, other).findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, binaryOnly);
+			}
+			return orBetter.apply(suggestedAnswer, other).findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
+		};
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java
new file mode 100644
index 0000000..b209866
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ModuleReferenceImpl.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class ModuleReferenceImpl implements IModule.IModuleReference {
+	public char[] name;
+	public int modifiers;
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+	public boolean equals(Object o) {
+		if (this == o) 
+			return true;
+		if (!(o instanceof IModule.IModuleReference))
+			return false;
+		IModule.IModuleReference mod = (IModule.IModuleReference) o;
+		if (this.modifiers != mod.getModifiers())
+			return false;
+		return CharOperation.equals(this.name, mod.name());
+	}
+	@Override
+	public int hashCode() {
+		return this.name.hashCode();
+	}
+	@Override
+	public int getModifiers() {
+		return this.modifiers;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index 03b8563..90922d3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -1,15 +1,21 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.env;
 
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
+
 public class NameEnvironmentAnswer {
 
 	// only one of the three can be set
@@ -17,22 +23,38 @@
 	ICompilationUnit compilationUnit;
 	ISourceType[] sourceTypes;
 	AccessRestriction accessRestriction;
+	char[] module;
 	String externalAnnotationPath; // should be an absolute file system path
 
 	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
 		this.binaryType = binaryType;
 		this.accessRestriction = accessRestriction;
+		this.module = binaryType.getModule();
 	}
 
+	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction, char[] module) {
+		this.binaryType = binaryType;
+		this.accessRestriction = accessRestriction;
+		this.module = module;
+	}
 	public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction) {
+		this(compilationUnit, accessRestriction, compilationUnit.module());
+	}
+	public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction, char[] module) {
 		this.compilationUnit = compilationUnit;
 		this.accessRestriction = accessRestriction;
+		this.module = module;
 	}
 
 	public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath) {
+		this(sourceTypes, accessRestriction, externalAnnotationPath, ModuleEnvironment.UNNAMED);
+	}
+
+	public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath, char[] module) {
 		this.sourceTypes = sourceTypes;
 		this.accessRestriction = accessRestriction;
 		this.externalAnnotationPath = externalAnnotationPath;
+		this.module = module;
 	}
 	
 	@Override
@@ -124,6 +146,9 @@
 	public boolean ignoreIfBetter() {
 		return this.accessRestriction != null && this.accessRestriction.ignoreIfBetter();
 	}
+	public char[] moduleName() {
+		return this.module;
+	}
 
 	/*
 	 * Returns whether this answer is better than the other awswer.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java
new file mode 100644
index 0000000..06cc2a2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/PackageExportImpl.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+public class PackageExportImpl implements IModule.IPackageExport {
+	public char[] pack;
+	public char[][] exportedTo;
+	@Override
+	public char[] name() {
+		return this.pack;
+	}
+
+	@Override
+	public char[][] targets() {
+		return this.exportedTo;
+	}
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(this.pack);
+		buffer.append(" to "); //$NON-NLS-1$
+		if (this.exportedTo != null) {
+			for (int i = 0; i < this.exportedTo.length; i++) {
+				if (i > 0) {
+					buffer.append(", "); //$NON-NLS-1$
+				}
+				char[] cs = this.exportedTo[i];
+				buffer.append(cs);
+			}
+		}
+		buffer.append(';');
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index a0cc71d..68ac66e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Benjamin Muskalla - Contribution for bug 239066
@@ -211,7 +215,7 @@
 	public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$
 	public static final String VERSION_1_7 = "1.7"; //$NON-NLS-1$
 	public static final String VERSION_1_8 = "1.8"; //$NON-NLS-1$
-	public static final String VERSION_1_9 = "1.9"; //$NON-NLS-1$
+	public static final String VERSION_9 = "9"; //$NON-NLS-1$
 	public static final String ERROR = "error"; //$NON-NLS-1$
 	public static final String WARNING = "warning"; //$NON-NLS-1$
 	public static final String INFO = "info"; //$NON-NLS-1$
@@ -768,9 +772,9 @@
 				if (jdkLevel == ClassFileConstants.JDK1_8)
 					return VERSION_1_8;
 				break;
-			case ClassFileConstants.MAJOR_VERSION_1_9 :
-				if (jdkLevel == ClassFileConstants.JDK1_9)
-					return VERSION_1_9;
+			case ClassFileConstants.MAJOR_VERSION_9 :
+				if (jdkLevel == ClassFileConstants.JDK9)
+					return VERSION_9;
 				break;
 		}
 		return Util.EMPTY_STRING; // unknown version
@@ -779,28 +783,34 @@
 	public static long versionToJdkLevel(String versionID) {
 		String version = versionID;
 		// verification is optimized for all versions with same length and same "1." prefix
-		if (version != null && version.length() == 3 && version.charAt(0) == '1' && version.charAt(1) == '.') {
-			switch (version.charAt(2)) {
-				case '1':
-					return ClassFileConstants.JDK1_1;
-				case '2':
-					return ClassFileConstants.JDK1_2;
-				case '3':
-					return ClassFileConstants.JDK1_3;
-				case '4':
-					return ClassFileConstants.JDK1_4;
-				case '5':
-					return ClassFileConstants.JDK1_5;
-				case '6':
-					return ClassFileConstants.JDK1_6;
-				case '7':
-					return ClassFileConstants.JDK1_7;
-				case '8':
-					return ClassFileConstants.JDK1_8;
-				case '9':
-					return ClassFileConstants.JDK1_9;
-				default:
-					return 0; // unknown
+		if (version != null && version.length() > 0) {
+			if (version.length() == 3 && version.charAt(0) == '1' && version.charAt(1) == '.') {
+				switch (version.charAt(2)) {
+					case '1':
+						return ClassFileConstants.JDK1_1;
+					case '2':
+						return ClassFileConstants.JDK1_2;
+					case '3':
+						return ClassFileConstants.JDK1_3;
+					case '4':
+						return ClassFileConstants.JDK1_4;
+					case '5':
+						return ClassFileConstants.JDK1_5;
+					case '6':
+						return ClassFileConstants.JDK1_6;
+					case '7':
+						return ClassFileConstants.JDK1_7;
+					case '8':
+						return ClassFileConstants.JDK1_8;
+					default:
+						return 0; // unknown
+				}
+			} else {
+				switch (version.charAt(0)) {
+					case '9':
+						return ClassFileConstants.JDK9;
+					// No default - let it go through the remaining checks.
+				}
 			}
 		}
 		if (VERSION_JSR14.equals(versionID)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
index cfd1fa7..8c39603 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
@@ -146,6 +146,8 @@
 		arraysize++;
 	if ((bits & TagBits.AnnotationForTypeParameter) != 0)
 		arraysize++;
+	if ((bits & TagBits.AnnotationForModule) != 0)
+		arraysize++;
 	
 	Object[] value = new Object[arraysize];
 	if (arraysize > 0) {
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 601dd60..ea212f0 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -82,6 +86,7 @@
 	protected MethodBinding[] methods;
 	protected ReferenceBinding[] memberTypes;
 	protected TypeVariableBinding[] typeVariables;
+	protected ModuleBinding module;
 	private BinaryTypeBinding prototype;
 
 	// For the link with the principle structure
@@ -265,7 +270,6 @@
 	this.environment = environment;
 	this.fPackage = packageBinding;
 	this.fileName = binaryType.getFileName();
-
 	/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we
 	   must internalize type variables and observe any parameterization of super class
 	   and/or super interfaces in order to be able to detect overriding in the presence
@@ -304,7 +308,10 @@
 	if (needFieldsAndMethods)
 		cachePartsFrom(binaryType, true);
 }
-
+public boolean canBeSeenBy(Scope sco) {
+	ModuleBinding mod = this.environment.getModule(sco.module());
+	return mod.canSee(this.fPackage) && super.canBeSeenBy(sco);
+}
 /**
  * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableFields()
  */
@@ -1806,7 +1813,7 @@
 			&& ((this.typeBits & (TypeIds.BitAnyNullAnnotation)) == 0))
 	{
 		// this will scan the annotations in package-info
-		ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME);
+		ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME, null);
 		if (packageInfo == null) {
 			packageBinding.defaultNullness = Binding.NO_NULL_DEFAULT;
 		}
@@ -1842,7 +1849,7 @@
 	IBinaryElementValuePair[] elementValuePairs = annotation.getElementValuePairs();
 	if (elementValuePairs == null || elementValuePairs.length == 0 ) {
 		// no argument: apply default default
-		ReferenceBinding annotationType = this.environment.getType(typeName);
+		ReferenceBinding annotationType = this.environment.getType(typeName, null);
 		if (annotationType == null) return 0;
 		if (annotationType.isUnresolvedType())
 			annotationType = ((UnresolvedReferenceBinding) annotationType).resolve(this.environment, false);
@@ -2096,4 +2103,7 @@
 	
 	return this.fields;
 }
+public ModuleBinding module() {
+	return this.module;
+}
 }
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 46fc51b..81f2ce3 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
@@ -28,6 +28,7 @@
 	public static final int METHOD = ASTNode.Bit4;
 	public static final int PACKAGE = ASTNode.Bit5;
 	public static final int IMPORT = ASTNode.Bit6;
+	public static final int MODULE = ASTNode.Bit7;
 	public static final int ARRAY_TYPE = TYPE | ASTNode.Bit7;
 	public static final int BASE_TYPE = TYPE | ASTNode.Bit8;
 	public static final int PARAMETERIZED_TYPE = TYPE | ASTNode.Bit9;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index 32de2db..48b4c2b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -497,7 +501,7 @@
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (currentIndex < length) {
 			unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]);
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
 			invocationSite.setFieldIndex(currentIndex);
 			if (binding == null) {
 				if (currentIndex == length) {
@@ -643,7 +647,7 @@
 	foundType : if (binding instanceof PackageBinding) {
 		while (currentIndex < length) {
 			PackageBinding packageBinding = (PackageBinding) binding;
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
 			if (binding == null) {
 				if (currentIndex == length) {
 					// must be a type if its the last name, otherwise we have no idea if its a package or type
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 a2eb9e2..d20f4d3 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for 
@@ -421,6 +425,7 @@
 		}
 
 		SourceTypeBinding sourceType = this.referenceContext.binding;
+		sourceType.module = environment().getModule(module());
 		environment().setAccessRestriction(sourceType, accessRestriction);
 		
 		TypeParameter[] typeParameters = this.referenceContext.typeParameters;
@@ -642,6 +647,16 @@
 				}
 			}
 		} else {
+			if (sourceType.isModule()) {
+				// TBD - allowed only at source level 9 or above
+				modifiers = ClassFileConstants.AccModule;
+				if ((realModifiers & ~(ClassFileConstants.ACC_OPEN | ClassFileConstants.AccModule)) != 0) {
+					problemReporter().illegalModifierForModule(compilationUnitScope().referenceContext.moduleDeclaration);
+				}
+				if ((realModifiers & ClassFileConstants.ACC_OPEN) != 0) {
+					modifiers |= ClassFileConstants.ACC_OPEN;
+				}
+			} else
 			// detect abnormal cases for classes
 			if (isMemberType) { // includes member types defined inside local types
 				final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStatic | ClassFileConstants.AccAbstract | ClassFileConstants.AccFinal | ClassFileConstants.AccStrictfp);
@@ -947,6 +962,8 @@
 		if (this.referenceContext.superclass == null) {
 			if (sourceType.isEnum() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
 				return connectEnumSuperclass();
+			if (sourceType.isModule())
+				return true;
 			sourceType.setSuperClass(getJavaLangObject());
 			return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
 		}
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 123289f..942f3c2 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Erling Ellingsen -  patch for bug 125570
@@ -91,11 +95,12 @@
 		this.topLevelTypes[i].scope.buildFieldsAndMethods();
 }
 void buildTypeBindings(AccessRestriction accessRestriction) {
+	char[] modName = module();
 	this.topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
 	boolean firstIsSynthetic = false;
 	if (this.referenceContext.compilationResult.compilationUnit != null) {
 		char[][] expectedPackageName = this.referenceContext.compilationResult.compilationUnit.getPackageName();
-		if (expectedPackageName != null
+		if (expectedPackageName != null && !this.referenceContext.isModuleInfo()
 				&& !CharOperation.equals(this.currentPackageName, expectedPackageName)) {
 
 			// only report if the unit isn't structurally empty
@@ -109,14 +114,14 @@
 	}
 	if (this.currentPackageName == CharOperation.NO_CHAR_CHAR) {
 		// environment default package is never null
-		this.fPackage = this.environment.defaultPackage;
+		this.fPackage = this.environment.getDefaultPackage(modName);
 	} else {
-		if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) {
+		if ((this.fPackage = this.environment.createPackage(this.currentPackageName, modName)) == null) {
 			if (this.referenceContext.currentPackage != null) {
 				problemReporter().packageCollidesWithType(this.referenceContext); // only report when the unit has a package statement
 			}
 			// ensure fPackage is not null
-			this.fPackage = this.environment.defaultPackage;
+			this.fPackage = this.environment.getDefaultPackage(modName);
 			return;
 		} else if (this.referenceContext.isPackageInfo()) {
 			// resolve package annotations now if this is "package-info.java".
@@ -129,6 +134,10 @@
 			if (this.referenceContext.currentPackage != null && this.referenceContext.currentPackage.annotations != null) {
 				this.referenceContext.types[0].annotations = this.referenceContext.currentPackage.annotations;
 			}
+		} else if (this.referenceContext.isModuleInfo()) {
+			ModuleDeclaration module = this.referenceContext.moduleDeclaration;
+			if (module != null)
+				module.moduleBinding = this.environment().getModule(module());
 		}
 		recordQualifiedReference(this.currentPackageName); // always dependent on your own package
 	}
@@ -151,10 +160,11 @@
 			// if a type exists, check that its a valid type
 			// it can be a NotFound problem type if its a secondary type referenced before its primary type found in additional units
 			// and it can be an unresolved type which is now being defined
-			problemReporter().duplicateTypes(this.referenceContext, typeDecl);
+			if (!typeBinding.isModule()) // Kludge?
+				problemReporter().duplicateTypes(this.referenceContext, typeDecl);
 			continue nextType;
 		}
-		if (this.fPackage != this.environment.defaultPackage && this.fPackage.getPackage(typeDecl.name) != null) {
+		if (this.fPackage != this.environment.getDefaultPackage(modName) && this.fPackage.getPackage(typeDecl.name, module()) != null) {
 			// if a package exists, it must be a valid package - cannot be a NotFound problem package
 			// this is now a warning since a package does not really 'exist' until it contains a type, see JLS v2, 7.4.3
 			problemReporter().typeCollidesWithPackage(this.referenceContext, typeDecl);
@@ -461,13 +471,13 @@
 }
 private Binding findImport(char[][] compoundName, int length) {
 	recordQualifiedReference(compoundName);
-
-	Binding binding = this.environment.getTopLevelPackage(compoundName[0]);
+	char[] modName = module();
+	Binding binding = this.environment.getTopLevelPackage(compoundName[0], modName);
 	int i = 1;
 	foundNothingOrType: if (binding != null) {
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (i < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[i++]);
+			binding = packageBinding.getTypeOrPackage(compoundName[i++], modName);
 			if (binding == null || !binding.isValidBinding()) {
 				binding = null;
 				break foundNothingOrType;
@@ -484,7 +494,8 @@
 	if (binding == null) {
 		if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
 			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
-		type = findType(compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage);
+		PackageBinding defaultPackage = this.environment.getDefaultPackage(modName);
+		type = findType(compoundName[0], defaultPackage, defaultPackage);
 		if (type == null || !type.isValidBinding())
 			return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
 		i = 1; // reset to look for member types inside the default package type
@@ -511,9 +522,9 @@
 	if (compoundName.length == 1) {
 		// findType records the reference
 		// the name cannot be a package
-		if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
+		if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4 && !this.referenceContext.isModuleInfo())
 			return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
-		ReferenceBinding typeBinding = findType(compoundName[0], this.environment.defaultPackage, this.fPackage);
+		ReferenceBinding typeBinding = findType(compoundName[0], this.environment.getDefaultPackage(module()), this.fPackage);
 		if (typeBinding == null)
 			return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
 		return typeBinding;
@@ -529,7 +540,7 @@
 
 	char[] name = compoundName[compoundName.length - 1];
 	if (binding instanceof PackageBinding) {
-		Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
+		Binding temp = ((PackageBinding) binding).getTypeOrPackage(name, module());
 		if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type
 			return new ProblemReferenceBinding(compoundName, (ReferenceBinding) temp, ProblemReasons.InvalidTypeForStaticImport);
 		return binding; // cannot be a package, error is caught in sender
@@ -583,9 +594,9 @@
 	// initialize the default imports if necessary... share the default java.lang.* import
 	if (this.environment.defaultImports != null) return this.environment.defaultImports;
 
-	Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA);
+	Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA, module());
 	if (importBinding != null)
-		importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1]);
+		importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1], module());
 
 	if (importBinding == null || !importBinding.isValidBinding()) {
 		// create a proxy for the missing BinaryType
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 111d785..65a96c5 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - contributions for
@@ -56,6 +60,7 @@
 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfModule;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 
@@ -67,7 +72,8 @@
 	 */
 	private Map accessRestrictions;
 	ImportBinding[] defaultImports;
-	public PackageBinding defaultPackage;
+	private PackageBinding defaultPackage;
+	private HashtableOfPackage defaultPackages;
 	HashtableOfPackage knownPackages;
 	private int lastCompletedUnitIndex = -1;
 	private int lastUnitIndex = -1;
@@ -92,6 +98,9 @@
 	private SimpleLookupTable uniquePolymorphicMethodBindings;
 	private SimpleLookupTable uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734
 
+	// key is a string with the module name value is a module binding
+	HashtableOfModule knownModules;
+
 	public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
 	public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems
 	private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
@@ -123,7 +132,7 @@
 
 	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
 	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
-
+	final ModuleBinding UnNamedModule;
 
 public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
 	this.typeRequestor = typeRequestor;
@@ -132,6 +141,7 @@
 	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
 	this.defaultImports = null;
 	this.nameEnvironment = nameEnvironment;
+	this.defaultPackages = new HashtableOfPackage();
 	this.knownPackages = new HashtableOfPackage();
 	this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
 	this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
@@ -140,44 +150,100 @@
 	this.classFilePool = ClassFilePool.newInstance();
 	this.typesBeingConnected = new HashSet<>();
 	this.typeSystem = this.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8 && this.globalOptions.storeAnnotations ? new AnnotatableTypeSystem(this) : new TypeSystem(this);
+	this.knownModules = new HashtableOfModule(5);
+	this.UnNamedModule = new ModuleBinding.UnNamedModule(this);
 }
 
+public ReferenceBinding askForType(char[][] compoundName) {
+	return askForType(compoundName, null);
+}
+public ModuleBinding getModule(char[] name) {
+	if (name == null || name.length == 0 || CharOperation.equals(name, ModuleEnvironment.UNNAMED))
+		return this.UnNamedModule;
+	ModuleBinding module = this.knownModules.get(name);
+	if (module == null) {
+		if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+			IModule mod = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModule(name);
+			if (mod != null) {
+				this.knownModules.put(name, module = new ModuleBinding(mod, this));
+			}
+		} else 
+			return this.UnNamedModule;
+	}
+	return module;
+}
 /**
  * Ask the name environment for a type which corresponds to the compoundName.
  * Answer null if the name cannot be found.
  */
 
-public ReferenceBinding askForType(char[][] compoundName) {
-	NameEnvironmentAnswer answer = this.nameEnvironment.findType(compoundName);
+public ReferenceBinding askForType(char[][] compoundName, char[] mod) {
+	NameEnvironmentAnswer answer = null;
+	if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+		ModuleBinding module = getModule(mod);
+		answer = ((IModuleAwareNameEnvironment)this.nameEnvironment).findType(compoundName, module.getDependencyClosureContext());
+	} else {
+		answer = this.nameEnvironment.findType(compoundName);
+	}
 	if (answer == null) return null;
-
 	if (answer.isBinaryType()) {
 		// the type was found as a .class file
-		this.typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction());
+		PackageBinding pkg = computePackageFrom(compoundName, false /* valid pkg */);
+		this.typeRequestor.accept(answer.getBinaryType(), pkg, answer.getAccessRestriction());
+		ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]);
+		if (binding instanceof BinaryTypeBinding) {
+			((BinaryTypeBinding) binding).module = getModule(answer.moduleName());
+		}
 	} else if (answer.isCompilationUnit()) {
 		// the type was found as a .java file, try to build it then search the cache
 		this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
 	} else if (answer.isSourceType()) {
 		// the type was found as a source model
-		this.typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName, false /* valid pkg */), answer.getAccessRestriction());
+		PackageBinding pkg = computePackageFrom(compoundName, false /* valid pkg */);
+		this.typeRequestor.accept(answer.getSourceTypes(), pkg, answer.getAccessRestriction());
+		ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]);
+		if (binding instanceof SourceTypeBinding) {
+			((SourceTypeBinding) binding).module = getModule(answer.moduleName());
+		}
 	}
 	return getCachedType(compoundName);
 }
+ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
+	return askForType(packageBinding, name, null);
+}
 /* Ask the oracle for a type named name in the packageBinding.
 * Answer null if the name cannot be found.
 */
 
-ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
+ReferenceBinding askForType(PackageBinding packageBinding, char[] name, char[] mod) {
 	if (packageBinding == null) {
 		packageBinding = this.defaultPackage;
 	}
-	NameEnvironmentAnswer answer = this.nameEnvironment.findType(name, packageBinding.compoundName);
+	NameEnvironmentAnswer answer = null;
+	if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+		ModuleBinding module = getModule(mod);
+		if (module != null) {
+				answer = ((IModuleAwareNameEnvironment) this.nameEnvironment).findType(name,
+						packageBinding.compoundName, module.getDependencyClosureContext());
+		}
+	} else {
+		answer = this.nameEnvironment.findType(name, packageBinding.compoundName);
+	}
 	if (answer == null)
 		return null;
 
+	char[] module = answer.moduleName();
+//	if (module != null && !CharOperation.equals(module, JRTUtil.JAVA_BASE.toCharArray()) 
+//			&& !this.nameEnvironment.isPackageVisible(packageBinding.readableName(), module, mod)) {
+//		return null;
+//	}
 	if (answer.isBinaryType()) {
 		// the type was found as a .class file
 		this.typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction());
+		ReferenceBinding binding = packageBinding.getType0(name);
+		if (binding instanceof BinaryTypeBinding) {
+			((BinaryTypeBinding) binding).module = getModule(module);
+		}
 	} else if (answer.isCompilationUnit()) {
 		// the type was found as a .java file, try to build it then search the cache
 		try {
@@ -191,6 +257,9 @@
 		// the type was found as a source model
 		this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
 		ReferenceBinding binding = packageBinding.getType0(name);
+		if (binding instanceof SourceTypeBinding) {
+			((SourceTypeBinding) binding).module = getModule(module);
+		}
 		String externalAnnotationPath = answer.getExternalAnnotationPath();
 		if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) {
 			ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath);
@@ -199,6 +268,10 @@
 	}
 	return packageBinding.getType0(name);
 }
+public boolean canTypeBeSeen(SourceTypeBinding binding, Scope scope) {
+	ModuleBinding client = getModule(scope.module());
+	return client.canSee(binding.fPackage);
+}
 
 /* Create the initial type bindings for the compilation unit.
 *
@@ -369,35 +442,35 @@
 			return TypeBinding.LONG;
 
 		case TypeIds.T_int :
-			boxedType = getType(JAVA_LANG_INTEGER);
+			boxedType = getType(JAVA_LANG_INTEGER, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_INTEGER, null, NotFound);
 		case TypeIds.T_byte :
-			boxedType = getType(JAVA_LANG_BYTE);
+			boxedType = getType(JAVA_LANG_BYTE, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_BYTE, null, NotFound);
 		case TypeIds.T_short :
-			boxedType = getType(JAVA_LANG_SHORT);
+			boxedType = getType(JAVA_LANG_SHORT, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_SHORT, null, NotFound);
 		case TypeIds.T_char :
-			boxedType = getType(JAVA_LANG_CHARACTER);
+			boxedType = getType(JAVA_LANG_CHARACTER, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_CHARACTER, null, NotFound);
 		case TypeIds.T_long :
-			boxedType = getType(JAVA_LANG_LONG);
+			boxedType = getType(JAVA_LANG_LONG, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_LONG, null, NotFound);
 		case TypeIds.T_float :
-			boxedType = getType(JAVA_LANG_FLOAT);
+			boxedType = getType(JAVA_LANG_FLOAT, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_FLOAT, null, NotFound);
 		case TypeIds.T_double :
-			boxedType = getType(JAVA_LANG_DOUBLE);
+			boxedType = getType(JAVA_LANG_DOUBLE, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_DOUBLE, null, NotFound);
 		case TypeIds.T_boolean :
-			boxedType = getType(JAVA_LANG_BOOLEAN);
+			boxedType = getType(JAVA_LANG_BOOLEAN, null);
 			if (boxedType != null) return boxedType;
 			return new ProblemReferenceBinding(JAVA_LANG_BOOLEAN, null, NotFound);
 //		case TypeIds.T_int :
@@ -731,7 +804,7 @@
 	MissingTypeBinding missingType = new MissingTypeBinding(packageBinding, compoundName, this);
 	if (missingType.id != TypeIds.T_JavaLangObject) {
 		// make Object be its superclass - it could in turn be missing as well
-		ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT);
+		ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT, null);
 		if (objectType == null) {
 			objectType = createMissingType(null, TypeConstants.JAVA_LANG_OBJECT);	// create a proxy for the missing Object type
 		}
@@ -744,12 +817,27 @@
 	return missingType;
 }
 
+public PackageBinding getDefaultPackage(char[] module) {
+	if (module == null || module.length == 0 || module == ModuleEnvironment.UNNAMED) {
+		return this.defaultPackage;
+	} else {
+		PackageBinding pack = this.defaultPackages.get(module);
+		if (pack == null) {
+			pack = new PackageBinding(this);
+			this.defaultPackages.put(module, pack);
+		}
+		return pack;
+	}
+}
+public PackageBinding createPackage(char[][] compoundName) {
+	return createPackage(compoundName, null);
+}
 /*
 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
 * 2. Create the field bindings
 * 3. Create the method bindings
 */
-public PackageBinding createPackage(char[][] compoundName) {
+public PackageBinding createPackage(char[][] compoundName, char[] mod) {
 	PackageBinding packageBinding = getPackage0(compoundName[0]);
 	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
 		packageBinding = new PackageBinding(compoundName[0], this);
@@ -774,10 +862,11 @@
 			// since the package can be added after a set of source files have already been compiled,
 			// we need to check whenever a package is created
 			if(this.nameEnvironment instanceof INameEnvironmentExtension) {
+				ModuleBinding module = getModule(mod);
 				//When the nameEnvironment is an instance of INameEnvironmentWithProgress, it can get avoided to search for secondaryTypes (see flag).
 				// This is a performance optimization, because it is very expensive to search for secondary types and it isn't necessary to check when creating a package,
 				// because package name can not collide with a secondary type name.
-				if (((INameEnvironmentExtension)this.nameEnvironment).findType(compoundName[i], parent.compoundName, false) != null) {
+				if (((INameEnvironmentExtension)this.nameEnvironment).findType(compoundName[i], parent.compoundName, false, module.getDependencyClosureContext()) != null) {
 					return null;
 				}
 			} else {
@@ -884,7 +973,7 @@
 	for (int i = 0; i < parametersLength; i++) {
 		TypeBinding parameterTypeBinding = parameters[i];
 		if (parameterTypeBinding.id == TypeIds.T_null) {
-			parametersTypeBinding[i] = getType(JAVA_LANG_VOID);
+			parametersTypeBinding[i] = getType(JAVA_LANG_VOID, null);
 		} else {
 			parametersTypeBinding[i] = parameterTypeBinding.erasure();
 		}
@@ -1180,8 +1269,8 @@
 	this.globalOptions.useNullTypeAnnotations = Boolean.FALSE;
 	if (!this.globalOptions.isAnnotationBasedNullAnalysisEnabled || this.globalOptions.originalSourceLevel < ClassFileConstants.JDK1_8)
 		return;
-	ReferenceBinding nullable = this.nullableAnnotation != null ? this.nullableAnnotation.getAnnotationType() : getType(this.getNullableAnnotationName());
-	ReferenceBinding nonNull = this.nonNullAnnotation != null ? this.nonNullAnnotation.getAnnotationType() : getType(this.getNonNullAnnotationName());
+	ReferenceBinding nullable = this.nullableAnnotation != null ? this.nullableAnnotation.getAnnotationType() : getType(this.getNullableAnnotationName(), null);
+	ReferenceBinding nonNull = this.nonNullAnnotation != null ? this.nonNullAnnotation.getAnnotationType() : getType(this.getNonNullAnnotationName(), null);
 	if (nullable == null && nonNull == null)
 		return;
 	if (nullable == null || nonNull == null)
@@ -1211,7 +1300,7 @@
 * Fail with a classpath error if the type cannot be found.
 */
 public ReferenceBinding getResolvedType(char[][] compoundName, Scope scope) {
-	ReferenceBinding type = getType(compoundName);
+	ReferenceBinding type = getType(compoundName, scope == null ? null : scope.module());
 	if (type != null) return type;
 
 	// create a proxy for the missing BinaryType
@@ -1227,16 +1316,25 @@
 * Ask the oracle for the package if its not in the cache.
 * Answer null if the package cannot be found.
 */
-PackageBinding getTopLevelPackage(char[] name) {
+PackageBinding getTopLevelPackage(char[] name, char[] mod) {
 	PackageBinding packageBinding = getPackage0(name);
 	if (packageBinding != null) {
 		if (packageBinding == TheNotFoundPackage)
 			return null;
 		return packageBinding;
 	}
-
-	if (this.nameEnvironment.isPackage(null, name)) {
-		this.knownPackages.put(name, packageBinding = new PackageBinding(name, this));
+	if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+		ModuleBinding module = getModule(mod);
+		if (module != null)
+			packageBinding = module.getPackage(null, name);
+	} else {
+		if (this.nameEnvironment.isPackage(null, name)) {
+			packageBinding = new PackageBinding(name, this);
+		}
+	}
+	if (packageBinding != null) {
+	//if (this.nameEnvironment.isPackage(null, name, mod)) {
+		this.knownPackages.put(name, packageBinding);
 		return packageBinding;
 	}
 
@@ -1244,11 +1342,14 @@
 	return null;
 }
 
+public ReferenceBinding getType(char[][] compoundName) {
+	return getType(compoundName, null);
+}
 /* Answer the type corresponding to the compoundName.
 * Ask the name environment for the type if its not in the cache.
 * Answer null if the type cannot be found.
 */
-public ReferenceBinding getType(char[][] compoundName) {
+public ReferenceBinding getType(char[][] compoundName, char[] mod) {
 	ReferenceBinding referenceBinding;
 
 	if (compoundName.length == 1) {
@@ -1256,7 +1357,7 @@
 			PackageBinding packageBinding = getPackage0(compoundName[0]);
 			if (packageBinding != null && packageBinding != TheNotFoundPackage)
 				return null; // collides with a known package... should not call this method in such a case
-			referenceBinding = askForType(this.defaultPackage, compoundName[0]);
+			referenceBinding = askForType(this.defaultPackage, compoundName[0], mod);
 		}
 	} else {
 		PackageBinding packageBinding = getPackage0(compoundName[0]);
@@ -1273,9 +1374,9 @@
 		}
 
 		if (packageBinding == null)
-			referenceBinding = askForType(compoundName);
+			referenceBinding = askForType(compoundName, mod);
 		else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null)
-			referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]);
+			referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1], mod);
 	}
 
 	if (referenceBinding == null || referenceBinding == TheNotFoundType)
@@ -1670,13 +1771,6 @@
 	return false;
 }
 
-/* Ask the oracle if a package exists named name in the package named compoundName.
-*/
-boolean isPackage(char[][] compoundName, char[] name) {
-	if (compoundName == null || compoundName.length == 0)
-		return this.nameEnvironment.isPackage(null, name);
-	return this.nameEnvironment.isPackage(compoundName, name);
-}
 // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
 public MethodVerifier methodVerifier() {
 	if (this.verifier == null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
index 357672d..7da4ba3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
@@ -1,9 +1,13 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
@@ -85,4 +89,7 @@
     	return "Member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
     }
 }
+public ModuleBinding module() {
+	return this.enclosingType.module();
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 985e414..25cea65 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ *  * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -165,6 +169,7 @@
 
 /**
  * Spec : 8.4.3 & 9.4
+ * TODO: Add the spec section number for private interface methods from jls 9
  */
 private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
 	int modifiers = methodBinding.modifiers;
@@ -174,17 +179,16 @@
 
 	// after this point, tests on the 16 bits reserved.
 	int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
-
+	long sourceLevel = compilerOptions().sourceLevel;
 	// set the requested modifiers for a method in an interface/annotation
 	if (declaringClass.isInterface()) {
 		int expectedModifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
 		boolean isDefaultMethod = (modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0; // no need to check validity, is done by the parser
 		boolean reportIllegalModifierCombination = false;
-		boolean isJDK18orGreater = false;
-		if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8 && !declaringClass.isAnnotationType()) {
+		if (sourceLevel >= ClassFileConstants.JDK1_8 && !declaringClass.isAnnotationType()) {
 			expectedModifiers |= ClassFileConstants.AccStrictfp
 					| ExtraCompilerModifiers.AccDefaultMethod | ClassFileConstants.AccStatic;
-			isJDK18orGreater = true;
+			expectedModifiers |= sourceLevel >= ClassFileConstants.JDK9 ? ClassFileConstants.AccPrivate : 0;
 			if (!methodBinding.isAbstract()) {
 				reportIllegalModifierCombination = isDefaultMethod && methodBinding.isStatic();
 			} else {
@@ -195,6 +199,14 @@
 			}
 			if (reportIllegalModifierCombination) {
 				problemReporter().illegalModifierCombinationForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext);
+			} 
+			if (sourceLevel >= ClassFileConstants.JDK9 && (methodBinding.modifiers & ClassFileConstants.AccPrivate) != 0) {
+				int remaining = realModifiers & ~expectedModifiers;
+				if (remaining == 0) { // check for the combination of allowed modifiers with private
+					remaining = realModifiers & ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccStrictfp);
+					if (isDefaultMethod || remaining != 0)
+						problemReporter().illegalModifierCombinationForPrivateInterfaceMethod((AbstractMethodDeclaration) this.referenceContext);
+				}
 			}
 			// Kludge - The AccDefaultMethod bit is outside the lower 16 bits and got removed earlier. Putting it back.
 			if (isDefaultMethod) {
@@ -205,10 +217,22 @@
 			if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0)
 				problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) this.referenceContext);
 			else
-				problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext, isJDK18orGreater);
+				problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) this.referenceContext, sourceLevel);
 			methodBinding.modifiers &= (expectedModifiers | ~ExtraCompilerModifiers.AccJustFlag);
 		}
 		return;
+	} else if (declaringClass.isAnonymousType() && sourceLevel >= ClassFileConstants.JDK9) {
+		// If the class instance creation expression elides the supertype's type arguments using '<>',
+		// then for all non-private methods declared in the class body, it is as if the method declaration
+		// is annotated with @Override - https://bugs.openjdk.java.net/browse/JDK-8073593
+		LocalTypeBinding local = (LocalTypeBinding) declaringClass;
+		TypeReference ref = local.scope.referenceContext.allocation.type;
+		if (ref != null && (ref.bits & ASTNode.IsDiamond) != 0) {
+			// 
+			if ((realModifiers & (ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic )) == 0) {
+				methodBinding.tagBits |= TagBits.AnnotationOverride;
+			}
+		}
 	}
 
 	// check for abnormal modifiers
@@ -343,6 +367,7 @@
 	// is necessary to ensure error reporting
 	this.referenceContext = method;
 	method.scope = this;
+	long sourceLevel = compilerOptions().sourceLevel;
 	SourceTypeBinding declaringClass = referenceType().binding;
 	int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved;
 	if (method.isConstructor()) {
@@ -352,7 +377,9 @@
 		checkAndSetModifiersForConstructor(method.binding);
 	} else {
 		if (declaringClass.isInterface()) {// interface or annotation type
-			if (method.isDefaultMethod() || method.isStatic()) {
+			if (sourceLevel >= ClassFileConstants.JDK9 && ((method.modifiers & ClassFileConstants.AccPrivate) != 0)) { // private method
+				// do nothing
+			} else if (method.isDefaultMethod() || method.isStatic()) {
 				modifiers |= ClassFileConstants.AccPublic; // default method is not abstract
 			} else {
 				modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
@@ -366,7 +393,6 @@
 
 	Argument[] argTypes = method.arguments;
 	int argLength = argTypes == null ? 0 : argTypes.length;
-	long sourceLevel = compilerOptions().sourceLevel;
 	if (argLength > 0) {
 		Argument argument = argTypes[--argLength];
 		if (argument.isVarArgs() && sourceLevel >= ClassFileConstants.JDK1_5)
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
new file mode 100644
index 0000000..ec463c3
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
@@ -0,0 +1,444 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+
+public class ModuleBinding extends Binding {
+
+	public static class UnNamedModule extends ModuleBinding {
+
+		UnNamedModule(LookupEnvironment env) {
+			super(env);
+		}
+		public ModuleBinding[] getAllRequiredModules() {
+			return NO_REQUIRES;
+		}
+		public IModuleContext getModuleLookupContext() {
+			return IModuleContext.UNNAMED_MODULE_CONTEXT;
+		}
+		public IModuleContext getDependencyClosureContext() {
+			return IModuleContext.UNNAMED_MODULE_CONTEXT;
+		}
+		public IModuleContext getModuleGraphContext() {
+			return IModuleContext.UNNAMED_MODULE_CONTEXT;
+		}
+		public boolean canSee(PackageBinding pkg) {
+			//TODO - if the package is part of a named module, then we should check if the module exports the package
+			return true;
+		}
+	}
+	public char[] moduleName;
+	public IModuleReference[] requires;
+	public IPackageExport[] exports;
+	public TypeBinding[] uses;
+	public TypeBinding[] services;
+	public TypeBinding[] implementations;
+	public CompilationUnitScope scope;
+	public LookupEnvironment environment;
+	public int tagBits;
+	private ModuleBinding[] requiredModules = null;
+	private boolean isAuto;
+
+	HashtableOfPackage declaredPackages;
+	HashtableOfPackage exportedPackages;
+
+	public static ModuleBinding[] NO_REQUIRES = new ModuleBinding[0];
+
+	ModuleBinding(LookupEnvironment env) {
+		this.moduleName = ModuleEnvironment.UNNAMED;
+		this.environment = env;
+		this.requires = IModule.NO_MODULE_REFS;
+		this.exports = IModule.NO_EXPORTS;
+		this.declaredPackages = new HashtableOfPackage(0);
+		this.exportedPackages = new HashtableOfPackage(0);
+	}
+	public ModuleBinding(IModule module, LookupEnvironment environment) {
+		this.moduleName = module.name();
+		IModule decl = module;
+		this.requires = decl.requires();
+		if (this.requires == null)
+			this.requires = IModule.NO_MODULE_REFS;
+		this.exports = decl.exports();
+		if (this.exports == null)
+			this.exports = IModule.NO_EXPORTS;
+		this.environment = environment;
+		this.uses = Binding.NO_TYPES;
+		this.services = Binding.NO_TYPES;
+		this.implementations = Binding.NO_TYPES;
+		this.declaredPackages = new HashtableOfPackage(5);
+		this.exportedPackages = new HashtableOfPackage(5);
+		this.isAuto = module.isAutomatic();
+	}
+
+	private Stream<ModuleBinding> getRequiredModules(boolean transitiveOnly) {
+		return Stream.of(this.requires).filter(ref -> transitiveOnly ? ref.isTransitive() : true)
+			.map(ref -> this.environment.getModule(ref.name()))
+			.filter(mod -> mod != null);
+	}
+	private void collectAllDependencies(Set<ModuleBinding> deps) {
+		getRequiredModules(false).forEach(m -> {
+			if (deps.add(m)) {
+				m.collectAllDependencies(deps);
+			}
+		});
+	}
+	private void collectTransitiveDependencies(Set<ModuleBinding> deps) {
+		getRequiredModules(true).forEach(m -> {
+			if (deps.add(m)) {
+				m.collectTransitiveDependencies(deps);
+			}
+		});
+	}
+
+	// All modules required by this module, either directly or indirectly
+	public Supplier<Collection<ModuleBinding>> dependencyGraphCollector() {
+		return () -> getRequiredModules(false)
+			.collect(HashSet::new,
+				(set, mod) -> {
+					set.add(mod);
+					mod.collectAllDependencies(set);
+				},
+				HashSet::addAll);
+	}
+	// All direct and transitive dependencies of this module
+	public Supplier<Collection<ModuleBinding>> dependencyCollector() {
+		return () -> getRequiredModules(false)
+			.collect(HashSet::new,
+				(set, mod) -> {
+					set.add(mod);
+					mod.collectTransitiveDependencies(set);
+				},
+				HashSet::addAll);
+	}
+
+	/**
+	 * Get all the modules required by this module
+	 * All required modules include modules explicitly specified as required in the module declaration
+	 * as well as implicit dependencies - those specified as ' requires public ' by one of the
+	 * dependencies
+	 * 
+	 * @return
+	 *   An array of all required modules
+	 */
+	public ModuleBinding[] getAllRequiredModules() {
+		if (this.requiredModules != null)
+			return this.requiredModules;
+
+		Collection<ModuleBinding> allRequires = dependencyCollector().get();
+		ModuleBinding javaBase = this.environment.getModule(JRTUtil.JAVA_BASE_CHAR);
+		if (!CharOperation.equals(this.moduleName, TypeConstants.JAVA_BASE) && javaBase != null) {
+			allRequires.add(javaBase);
+		}
+		return this.requiredModules = allRequires.size() > 0 ? allRequires.toArray(new ModuleBinding[allRequires.size()]) : NO_REQUIRES;
+	}
+
+	public char[] name() {
+		return this.moduleName;
+	}
+
+	/**
+	 * Check if the specified package is exported to the client module by this module. True if the package appears
+	 * in the list of exported packages and when the export is targeted, the module appears in the targets of the
+	 * exports statement
+	 * @param pkg - the package whose visibility is to be checked
+	 * @param client - the module that wishes to use the package
+	 * @return true if the package is visible to the client module, false otherwise
+	 */
+	public boolean isPackageExportedTo(PackageBinding pkg, ModuleBinding client) {
+		PackageBinding resolved = getExportedPackage(pkg.readableName());
+		if (resolved == pkg) {
+			if (this.isAuto) { // all packages are exported by an automatic module
+				return true;
+			}
+			Predicate<IPackageExport> isTargeted = IPackageExport::isQualified;
+			Predicate<IPackageExport> isExportedTo = e -> 
+				Stream.of(e.targets()).map(ref -> this.environment.getModule(ref)).filter(m -> m != null).anyMatch(client::equals);
+			
+			return Stream.of(this.exports).filter(e -> CharOperation.equals(pkg.readableName(), e.name()))
+					.anyMatch(isTargeted.negate().or(isExportedTo));
+		}
+		return false;
+	}
+	public PackageBinding getTopLevelPackage(char[] name) {
+		// return package binding if there exists a package named name in this module's context and it can be seen by this module
+		// A package can be seen by this module if it declares the package or someone exports that package to it
+		PackageBinding existing = this.environment.getPackage0(name);
+		if (existing != null) {
+			if (existing == LookupEnvironment.TheNotFoundPackage)
+				return null;
+		}
+		existing = getDeclaredPackage(new char[][] {name});
+		if (existing != null) {
+			return existing;
+		} else {
+			return Stream.of(getAllRequiredModules()).sorted((m1, m2) -> m1.requires.length - m2.requires.length)
+					.map(m -> {
+						PackageBinding binding = m.getExportedPackage(name);
+						if (binding != null && m.isPackageExportedTo(binding, this)) {
+							return m.declaredPackages.get(name);
+						}
+						return null;
+					})
+			.filter(p -> p != null).findFirst().orElse(null);
+		}
+	}
+	// Given parent is declared in this module, see if there is sub package named name declared in this module
+	private PackageBinding getDeclaredPackage(PackageBinding parent, char[] name) {
+		PackageBinding pkg = parent.getPackage0(name);
+		if (pkg != null && pkg != LookupEnvironment.TheNotFoundPackage)
+			return pkg;
+		if (declaresPackage(parent.compoundName, name)) {
+			char[][] subPkgCompoundName = CharOperation.arrayConcat(parent.compoundName, name);
+			PackageBinding binding = new PackageBinding(subPkgCompoundName, parent, this.environment);
+			parent.addPackage(binding);
+			this.declaredPackages.put(binding.readableName(), binding);
+			return binding;
+		}
+		// TODO: Situation can probably improved by adding NOtFoundPackage to this.declaredPackages 
+		//parent.addNotFoundPackage(name); Not a package in this module does not mean not a package at all
+		return null;
+	}
+	public PackageBinding getDeclaredPackage(char[][] name) {
+		// return package binding if there exists a package named name in this module
+		if (name == null || name.length == 0) {
+			return this.environment.getDefaultPackage(this.moduleName);
+		}
+
+		PackageBinding parent = null;
+		PackageBinding existing = this.environment.getPackage0(name[0]); 
+		if (existing != null) { // known top level package
+			if (existing == LookupEnvironment.TheNotFoundPackage)
+				return null;
+			parent = existing;
+		}
+		if (parent == null) {
+			if (declaresPackage(null, name[0])) { // unknown as yet, but declared in this module
+				parent = new PackageBinding(name[0], this.environment);
+				this.declaredPackages.put(name[0], parent);
+			} else {
+				this.declaredPackages.put(name[0], LookupEnvironment.TheNotFoundPackage); // not declared in this module
+				return null;
+			}
+		} else if (!declaresPackage(null, name[0])) { // already seen before, but not declared in this module
+			return null;
+		}
+		// check each sub package
+		for (int i = 1; i < name.length; i++) {
+			PackageBinding binding = getDeclaredPackage(parent, name[i]); 
+			if (binding == null) {
+				return null;
+			}
+			parent = binding;
+		}
+		return parent;
+	}
+	public PackageBinding getExportedPackage(char[] qualifiedPackageName) {
+		PackageBinding existing = this.exportedPackages.get(qualifiedPackageName);
+		if (existing != null && existing != LookupEnvironment.TheNotFoundPackage)
+			return existing;
+		if (this.isAuto) { // all packages are exported by an automatic module
+			return getDeclaredPackage(CharOperation.splitOn('.', qualifiedPackageName));
+		}
+		//Resolve exports to see if the package or a sub package is exported
+		return Stream.of(this.exports).sorted((e1, e2) -> e1.name().length - e2.name().length)
+		.filter(e -> CharOperation.prefixEquals(qualifiedPackageName, e.name())) // TODO: improve this
+		.map(e -> {
+			PackageBinding binding = getDeclaredPackage(CharOperation.splitOn('.', e.name()));
+			if (binding != null) {
+				this.exportedPackages.put(e.name(), binding);
+				return binding;
+			}
+			return null;
+		}).filter(p -> p != null).findFirst().orElse(null);
+	}
+	public boolean declaresPackage(PackageBinding p) {
+		PackageBinding pkg = this.declaredPackages.get(p.readableName());
+		if (pkg == null) {
+			pkg = getDeclaredPackage(p.compoundName);
+			if (pkg == p) {
+				this.declaredPackages.put(p.readableName(), p);
+				return true;
+			}
+		}
+		return pkg == p;
+	}
+	public boolean declaresPackage(char[][] parentPackageName, char[] name) {
+		char[] qualifiedName = CharOperation.concatWith(parentPackageName, name, '.');
+		PackageBinding declared = this.declaredPackages.get(qualifiedName);
+		if (declared != null && declared != LookupEnvironment.TheNotFoundPackage) {
+ 				return true;
+		}
+		INameEnvironment nameEnvironment = this.environment.nameEnvironment;
+		if (nameEnvironment instanceof IModuleAwareNameEnvironment) {
+			return ((IModuleAwareNameEnvironment)nameEnvironment).isPackage(parentPackageName, name, getModuleLookupContext());
+		} else {
+			return nameEnvironment.isPackage(parentPackageName, name);
+		}
+	}
+	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
+		PackageBinding binding = null;
+		if (parentPackageName == null || parentPackageName.length == 0) {
+			binding = getTopLevelPackage(packageName);
+		} else {
+			binding = getDeclaredPackage(parentPackageName);
+			if (binding != null && binding != LookupEnvironment.TheNotFoundPackage) {
+				binding = getDeclaredPackage(binding, packageName);
+				if (binding != null)
+					return binding;
+			}
+		}
+		if (binding == null) {
+			char[] qualifiedPackageName = CharOperation.concatWith(parentPackageName, packageName, '.');
+			return Stream.of(getAllRequiredModules())
+					.map(m -> {
+						if (m.isAuto) {
+							return m.getPackage(parentPackageName, packageName);
+						}
+						PackageBinding p = m.getExportedPackage(qualifiedPackageName);
+						if (p != null && m.isPackageExportedTo(p, this)) {
+							return m.declaredPackages.get(qualifiedPackageName);
+						}
+						return null;
+					})
+			.filter(p -> p != null).findFirst().orElse(null);
+		}
+		return binding;
+	}
+	/**
+	 * Check if the given package is visible to this module. True when the package is declared in
+	 * this module or exported by some required module to this module.
+	 * See {@link #isPackageExportedTo(PackageBinding, ModuleBinding)}
+	 * 
+	 * @param pkg
+	 * 
+	 * @return True, if the package is visible to this module, false otherwise
+	 */
+	public boolean canSee(PackageBinding pkg) {
+		return declaresPackage(pkg) || Stream.of(getAllRequiredModules()).anyMatch(
+				dep -> dep.isPackageExportedTo(pkg, ModuleBinding.this)
+		);
+	}
+	public boolean dependsOn(ModuleBinding other) {
+ 		if (other == this)
+ 			return true;
+		return Stream.of(getAllRequiredModules()).anyMatch(other::equals);
+	}
+	// A context representing just this module
+ 	public IModuleContext getModuleLookupContext() {
+ 		IModuleAwareNameEnvironment env = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
+ 		IModuleEnvironment moduleEnvironment = env.getModuleEnvironmentFor(this.moduleName);
+ 		return () -> moduleEnvironment == null ? Stream.empty() : Stream.of(moduleEnvironment);
+ 	}
+ 	// A context including this module and all it's required modules
+ 	public IModuleContext getDependencyClosureContext() {
+ 		if (this.isAuto)
+ 			return IModuleContext.UNNAMED_MODULE_CONTEXT;
+ 		ModuleBinding[] deps = getAllRequiredModules();
+ 		return getModuleLookupContext().includeAll(Stream.of(deps).map(m -> m.getModuleLookupContext()));
+ 	}
+ 	// A context that includes the entire module graph starting from this module
+ 	public IModuleContext getModuleGraphContext() {
+ 		Stream<ModuleBinding> reqs = getRequiredModules(false);
+ 		return getModuleLookupContext().includeAll(reqs.map(m -> m.getModuleGraphContext()).distinct());
+ 	}
+	@Override
+	public int kind() {
+		//
+		return Binding.MODULE;
+	}
+
+	@Override
+	public char[] readableName() {
+		//
+		return this.moduleName;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(30);
+		buffer.append("module " + new String(readableName())); //$NON-NLS-1$
+		if (this.requires.length > 0) {
+			buffer.append("\n/*    requires    */\n"); //$NON-NLS-1$
+			for (int i = 0; i < this.requires.length; i++) {
+				buffer.append("\n\t"); //$NON-NLS-1$
+				if (this.requires[i].isTransitive())
+					buffer.append("public "); //$NON-NLS-1$
+				buffer.append(this.requires[i].name());
+			}
+		} else {
+			buffer.append("\nNo Requires"); //$NON-NLS-1$
+		}
+		if (this.exports.length > 0) {
+			buffer.append("\n/*    exports    */\n"); //$NON-NLS-1$
+			for (int i = 0; i < this.exports.length; i++) {
+				IPackageExport export = this.exports[i];
+				buffer.append("\n\t"); //$NON-NLS-1$
+				buffer.append(export.name());
+				char[][] targets = export.targets();
+				if (targets != null) {
+					buffer.append("to "); //$NON-NLS-1$
+					for (int j = 0; j < targets.length; j++) {
+						if (j != 0)
+							buffer.append(", "); //$NON-NLS-1$
+						buffer.append(targets[j]);
+					}
+				}
+			}
+		} else {
+			buffer.append("\nNo Exports"); //$NON-NLS-1$
+		}
+		if (this.uses != null && this.uses.length > 0) {
+			buffer.append("\n/*    uses    /*\n"); //$NON-NLS-1$
+			for (int i = 0; i < this.uses.length; i++) {
+				buffer.append("\n\t"); //$NON-NLS-1$
+				buffer.append(this.uses[i].debugName());
+			}
+		} else {
+			buffer.append("\nNo Uses"); //$NON-NLS-1$
+		}
+		if (this.services != null && this.services.length > 0) {
+			buffer.append("\n/*    Services    */\n"); //$NON-NLS-1$
+			for (int i = 0; i < this.services.length; i++) {
+				buffer.append("\n\t"); //$NON-NLS-1$
+				buffer.append("provides "); //$NON-NLS-1$
+				buffer.append(this.services[i].debugName());
+				buffer.append(" with "); //$NON-NLS-1$
+				buffer.append(this.implementations[i].debugName());
+			}
+		} else {
+			buffer.append("\nNo Services"); //$NON-NLS-1$
+		}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java
new file mode 100644
index 0000000..e3e42cc
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleEnvironment.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+
+public abstract class ModuleEnvironment implements IModuleAwareNameEnvironment {
+	/*
+	 * Keeps track of packages mapped to modules
+	 * Knows how to get modules
+	 * Understands modules
+	 * Understand module dependencies and restrictions
+	 * Given a ModuleDeclaration, creates an IModuleDeclaration
+	 * TODO: This should kick-in only when source level is >= 9
+	 */
+	public static final char[] UNNAMED = "".toCharArray(); //$NON-NLS-1$
+	public static final IModule UNNAMED_MODULE = new IModule() {
+
+		@Override
+		public String toString() {
+			return new String(UNNAMED);
+		}
+
+		@Override
+		public char[] name() {
+			//
+			return UNNAMED;
+		}
+
+		@Override
+		public IModuleReference[] requires() {
+			return null;
+		}
+
+		@Override
+		public IPackageExport[] exports() {
+			return null;
+		}
+
+		@Override
+		public char[][] uses() {
+			return null;
+		}
+
+		@Override
+		public IService[] provides() {
+			return null;
+		}
+		@Override
+		public IPackageExport[] opens() {
+			return null;
+		}
+
+	};
+	public static final class AutoModule implements IModule {
+		char[] name;
+		public AutoModule(char[] name) {
+			this.name = name;
+		}
+		@Override
+		public char[] name() {
+			return this.name;
+		}
+
+		@Override
+		public IModuleReference[] requires() {
+			return IModule.NO_MODULE_REFS;
+		}
+
+		@Override
+		public IPackageExport[] exports() {
+			return IModule.NO_EXPORTS;
+		}
+
+		@Override
+		public char[][] uses() {
+			return IModule.NO_USES;
+		}
+
+		@Override
+		public IService[] provides() {
+			return IModule.NO_PROVIDES;
+		}
+
+		@Override
+		public IPackageExport[] opens() {
+			return NO_OPENS;
+		}
+
+		public boolean isAutomatic() {
+			return true;
+		}
+	}
+	public static IModule[] UNNAMED_MODULE_ARRAY = new IModule[]{UNNAMED_MODULE};
+
+	private HashMap<String, IModule> modulesCache = null;
+	private static HashMap<IModuleEnvironment, IModule> ModuleLocationMap = new HashMap<>();
+	
+	public ModuleEnvironment() {
+		this.modulesCache = new HashMap<>();
+	}
+
+	protected NameEnvironmentAnswer returnAnswerAfterValidation(char[][] packageName, NameEnvironmentAnswer answer, char[] client) {
+		if (isPackageVisible(CharOperation.concatWith(packageName, '.'), answer.moduleName(), client)) {
+			return answer;
+		}
+		return null;
+	}
+
+	// TODO: these should be abstract
+	public NameEnvironmentAnswer findType(char[][] compoundTypeName, IModuleContext moduleContext) {
+		return null;
+	}
+	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext moduleContext) {
+		return null;
+	}
+	public boolean isPackage(char[][] parentPackageName, char[] packageName, IModuleContext moduleContext) {
+		return false;
+	}
+
+	@Deprecated
+	public boolean isPackageVisible(char[] packageName, char[] sourceName, char[] clientName) {
+		boolean clientIsUnnamed = clientName == null || clientName == UNNAMED;
+		if (clientIsUnnamed)
+			return true; // Unnamed module can read every module
+		if (sourceName == null || sourceName == UNNAMED)
+			return clientIsUnnamed; // Unnamed module cannot be read by any named module
+
+		if (CharOperation.equals(sourceName, clientName)) 
+			return true;
+
+		IModule source = getModule(sourceName);
+		IModule client = getModule(clientName);
+		if (client != null) {
+					Set<IModule> set = new LinkedHashSet<>();
+					collectAllVisibleModules(client, set, false);
+					IModule[] targets = set.toArray(new IModule[set.size()]);
+					for (IModule iModule : targets) {
+						if (iModule == source && isPackageExportedTo(iModule, packageName, client)) {
+							return true;
+						}
+					}
+			return false;
+		}
+		return true;
+	}
+	/**
+	 * Tells whether the given module exports the given package to the specified client
+	 * module.
+	 *
+	 * @param module module whose exports being checked
+	 * @param pack package being exported
+	 * @param client requesting module
+	 * @return whether or not the specified package is exported from the module to the client
+	 */
+	protected boolean isPackageExportedTo(IModule module, char[] pack, IModule client) {
+		IModule.IPackageExport[] exports = module.exports();
+		if (exports != null && exports.length > 0) {
+			for (IModule.IPackageExport iPackageExport : exports) {
+				if (CharOperation.equals(iPackageExport.name(), pack)) {
+					char[][] exportedTo = iPackageExport.targets();
+					if (exportedTo == null || exportedTo.length == 0) {
+						return true;
+					}
+					for (char[] cs : exportedTo) {
+						if (CharOperation.equals(cs, client.name())) {
+							return true;
+						}
+					}
+					
+				}
+			}
+		}
+		return false;
+	}
+
+	public IModule[] getVisibleModules(char[] mod) {
+		IModule[] targets = new IModule[0];
+		if (mod != null && !CharOperation.equals(mod, UNNAMED)) {
+			Set<IModule> set = new LinkedHashSet<>();
+			IModule client = getModule(JRTUtil.JAVA_BASE.toCharArray());
+			if (client != null) set.add(client);
+			client = getModule(mod);
+			if (client != null) {
+				set.add(client);
+				collectAllVisibleModules(client, set, false);
+				targets = set.toArray(new IModule[set.size()]);
+			}
+		} else {
+			return UNNAMED_MODULE_ARRAY;
+		}
+		return targets;
+	}
+
+	protected void collectAllVisibleModules(IModule module, Set<IModule> targets, boolean onlyPublic) {
+		if (module != null) {
+			IModule.IModuleReference[] requires = module.requires();
+			if (requires != null && requires.length > 0) {
+				for (IModule.IModuleReference ref : requires) {
+					IModule refModule = getModule(ref.name());
+					if (refModule != null) {
+						if (!onlyPublic || ref.isTransitive()) {
+							targets.add(refModule);
+							collectAllVisibleModules(refModule, targets, true);
+						}
+					}
+				}
+			}
+		}
+	}
+	/**
+	 * Returns the module with the given name from the name environment.
+	 *
+	 * @param name the name of the module to lookup
+	 * @return the module with the given name
+	 */
+//	public IModuleDeclaration getModule(final char[] name) {
+////		if (name == null) return null;
+////		String mod = new String(name);
+////		IModuleDeclaration module = this.modulesCache.get(mod);
+////		return module;
+//		return name == null ? null : getModule(CharOperation.charToString(name));
+//	}
+	/**
+	 * Accepts the given module to be served later on requests. If 
+	 * any older copies of module already present, they will be 
+	 * overwritten by the new one.
+	 *
+	 * @param mod the module to be stored in memory
+	 */
+	public void acceptModule(IModule mod, IModuleEnvironment location) {
+		IModule existing = ModuleEnvironment.ModuleLocationMap.get(location);
+		if (existing != null) {
+			if (existing.equals(mod))
+				return;
+			else {
+				// Report problem and ignore the duplicate
+			}
+		}
+		String name = new String(mod.name());
+		this.modulesCache.put(name, mod);
+		ModuleEnvironment.ModuleLocationMap.put(location, mod);
+	}
+
+	//@Override
+	public IModule getModule(IModuleEnvironment location) {
+		IModule module = ModuleEnvironment.ModuleLocationMap.get(location);
+		if (module == null) 
+			return null;
+		String modName = new String(module.name());
+		if (this.modulesCache.get(modName) == null) {
+			this.modulesCache.put(modName, module);
+		}
+		return module;
+	}
+}
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 78325ab..51e3951 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -52,7 +56,7 @@
 public PackageBinding(LookupEnvironment environment) {
 	this(CharOperation.NO_CHAR_CHAR, null, environment);
 }
-private void addNotFoundPackage(char[] simpleName) {
+/*private*/ void addNotFoundPackage(char[] simpleName) {
 	this.knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
 }
 private void addNotFoundType(char[] simpleName) {
@@ -91,21 +95,24 @@
 public char[] computeUniqueKey(boolean isLeaf) {
 	return CharOperation.concatWith(this.compoundName, '/');
 }
-private PackageBinding findPackage(char[] name) {
-	if (!this.environment.isPackage(this.compoundName, name))
+private PackageBinding findPackage(char[] name, char[] mod) {
+	ModuleBinding module = this.environment.getModule(mod);
+	PackageBinding sub = module == null ? null : module.getPackage(this.compoundName, name);
+	if (sub == null)
 		return null;
 
-	char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
-	PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, this.environment);
-	addPackage(subPackageBinding);
-	return subPackageBinding;
+//	char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
+//	PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, this.environment);
+//	addPackage(subPackageBinding);
+//	return subPackageBinding;
+	return sub;
 }
 /* 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.
 *
 * NOTE: This should only be used when we know there is NOT a type with the same name.
 */
-PackageBinding getPackage(char[] name) {
+PackageBinding getPackage(char[] name, char[] mod) {
 	PackageBinding binding = getPackage0(name);
 	if (binding != null) {
 		if (binding == LookupEnvironment.TheNotFoundPackage)
@@ -113,7 +120,7 @@
 		else
 			return binding;
 	}
-	if ((binding = findPackage(name)) != null)
+	if ((binding = findPackage(name, mod)) != null)
 		return binding;
 
 	// not found so remember a problem package binding in the cache for future lookups
@@ -139,10 +146,10 @@
 * package with the same name.
 */
 
-ReferenceBinding getType(char[] name) {
+ReferenceBinding getType(char[] name, char[] mod) {
 	ReferenceBinding referenceBinding = getType0(name);
 	if (referenceBinding == null) {
-		if ((referenceBinding = this.environment.askForType(this, name)) == null) {
+		if ((referenceBinding = this.environment.askForType(this, name, mod)) == null) {
 			// not found so remember a problem type binding in the cache for future lookups
 			addNotFoundType(name);
 			return null;
@@ -180,7 +187,7 @@
 * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
 */
 
-public Binding getTypeOrPackage(char[] name) {
+public Binding getTypeOrPackage(char[] name, char[] mod) {
 	ReferenceBinding referenceBinding = getType0(name);
 	if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) {
 		referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this.environment, false /* no raw conversion for now */);
@@ -195,10 +202,11 @@
 
 	PackageBinding packageBinding = getPackage0(name);
 	if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) {
-		return packageBinding;
+		return (packageBinding.canBeSeenBy(mod)) ? packageBinding : null;
+		//return packageBinding;
 	}
 	if (referenceBinding == null) { // have not looked for it before
-		if ((referenceBinding = this.environment.askForType(this, name)) != null) {
+		if ((referenceBinding = this.environment.askForType(this, name, mod)) != null) {
 			if (referenceBinding.isNestedType()) {
 				return new ProblemReferenceBinding(new char[][]{name}, referenceBinding, ProblemReasons.InternalNameProvided);
 			}
@@ -211,13 +219,13 @@
 	}
 
 	if (packageBinding == null) { // have not looked for it before
-		if ((packageBinding = findPackage(name)) != null) {
+		if ((packageBinding = findPackage(name, mod)) != null) {
 			return packageBinding;
 		}
 		if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) {
 			return referenceBinding; // found cached missing type - check if package conflict
 		}
-		addNotFoundPackage(name);
+		//addNotFoundPackage(name); Not a package in module mod does not mean not a package at all
 	}
 
 	return null;
@@ -226,7 +234,7 @@
 	if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
 		this.tagBits |= TagBits.DeprecatedAnnotationResolved;
 		if (this.compoundName != CharOperation.NO_CHAR_CHAR) {
-			ReferenceBinding packageInfo = this.getType(TypeConstants.PACKAGE_INFO_NAME);
+			ReferenceBinding packageInfo = this.getType(TypeConstants.PACKAGE_INFO_NAME, null);
 			if (packageInfo != null) {
 				packageInfo.initializeDeprecatedAnnotationTagBits();
 				this.tagBits |= packageInfo.tagBits & TagBits.AllStandardAnnotationsMask;
@@ -260,7 +268,10 @@
 			env.nonnullByDefaultAnnotationPackage = this;
 	}
 }
-
+public boolean canBeSeenBy(char[] clientModule) {
+	ModuleBinding client = this.environment.getModule(clientModule);
+	return client.canSee(this);
+}
 private boolean isPackageOfQualifiedTypeName(char[][] packageName, char[][] typeName) {
 	int length;
 	if (typeName == null || (length = packageName.length) != typeName.length -1)
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 d5a1149..bc92b9c 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -1479,6 +1483,10 @@
 	return true;
 }
 
+public boolean isModule() {
+	return (this.modifiers & ClassFileConstants.AccModule) != 0;
+}
+
 public boolean isInterface() {
 	// consider strict interfaces and annotation types
 	return (this.modifiers & ClassFileConstants.AccInterface) != 0;
@@ -2200,4 +2208,7 @@
 	}
 	return true;
 }
+public ModuleBinding module() {
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 1a9997b..4de0914 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -691,7 +695,9 @@
 		} while (scope != null);
 		return (CompilationUnitScope) lastScope;
 	}
-	
+	public final char[] module() {
+		return compilationUnitScope().referenceCompilationUnit().module();
+	}
 	public boolean isLambdaScope() {
 		return false;
 	}
@@ -1953,7 +1959,7 @@
 		PackageBinding invocationPackage) {
 
 		compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
-		ReferenceBinding typeBinding = declarationPackage.getType(typeName);
+		ReferenceBinding typeBinding = declarationPackage.getType(typeName, module());
 		if (typeBinding == null)
 			return null;
 
@@ -2225,7 +2231,7 @@
 				// answer the problem type binding if we are only looking for a type
 			} else if ((mask & Binding.PACKAGE) != 0) {
 				unitScope.recordSimpleReference(name);
-				if ((binding = env.getTopLevelPackage(name)) != null)
+				if ((binding = env.getTopLevelPackage(name, module())) != null)
 					return binding;
 			}
 			if (problemField != null) return problemField;
@@ -2913,7 +2919,7 @@
 		int currentIndex = 1, length = compoundName.length;
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (currentIndex < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
 			if (binding == null) {
 				return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
 			}
@@ -2948,7 +2954,7 @@
 		int currentIndex = 1, length = compoundName.length;
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (currentIndex < length) {
-			binding = packageBinding.getPackage(compoundName[currentIndex++]);
+			binding = packageBinding.getPackage(compoundName[currentIndex++], module());
 			if (binding == null) {
 				return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
 			}
@@ -2984,7 +2990,7 @@
 		if (packageBinding == null)
 			return getType(name);
 
-		Binding binding = packageBinding.getTypeOrPackage(name);
+		Binding binding = packageBinding.getTypeOrPackage(name, module());
 		if (binding == null) {
 			return new ProblemReferenceBinding(
 				CharOperation.arrayConcat(packageBinding.compoundName, name),
@@ -3040,7 +3046,7 @@
 		if (binding instanceof PackageBinding) {
 			PackageBinding packageBinding = (PackageBinding) binding;
 			while (currentIndex < typeNameLength) {
-				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
+				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); // does not check visibility
 				if (binding == null) {
 					char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex);
 					return new ProblemReferenceBinding(
@@ -3261,7 +3267,7 @@
 			// check if the name is in the current package, skip it if its a sub-package
 			PackageBinding currentPackage = unitScope.fPackage;
 			unitScope.recordReference(currentPackage.compoundName, name);
-			Binding binding = currentPackage.getTypeOrPackage(name);
+			Binding binding = currentPackage.getTypeOrPackage(name, module());
 			if (binding instanceof ReferenceBinding) {
 				ReferenceBinding referenceType = (ReferenceBinding) binding;
 				if ((referenceType.tagBits & TagBits.HasMissingType) == 0) {
@@ -3320,7 +3326,7 @@
 
 		unitScope.recordSimpleReference(name);
 		if ((mask & Binding.PACKAGE) != 0) {
-			PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
+			PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name, module());
 			if (packageBinding != null && (packageBinding.tagBits & TagBits.HasMissingType) == 0) {
 				if (typeOrPackageCache != null)
 					typeOrPackageCache.put(name, packageBinding);
@@ -3337,7 +3343,7 @@
 					closestMatch = environment().createMissingType(unitScope.fPackage, qName);
 				}
 			} else {
-				PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
+				PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name, module());
 				if (packageBinding == null || !packageBinding.isValidBinding()) {
 					if (needResolve) {
 						closestMatch = environment().createMissingType(unitScope.fPackage, qName);
@@ -3376,7 +3382,7 @@
 			PackageBinding packageBinding = (PackageBinding) binding;
 
 			while (currentIndex < nameLength) {
-				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
 				if (binding == null)
 					return new ProblemReferenceBinding(
 						CharOperation.subarray(compoundName, 0, currentIndex),
@@ -4934,8 +4940,10 @@
 				break;
 			currentType = currentType.enclosingType();
 		}
+		boolean isInterface = allocationType.isInterface();
+		ReferenceBinding typeToSearch = isInterface ? getJavaLangObject() : allocationType;
 	
-		MethodBinding[] methods = allocationType.getMethods(TypeConstants.INIT, argumentTypes.length);
+		MethodBinding[] methods = typeToSearch.getMethods(TypeConstants.INIT, argumentTypes.length);
 		MethodBinding [] staticFactories = new MethodBinding[methods.length];
 		int sfi = 0;
 		for (int i = 0, length = methods.length; i < length; i++) {
@@ -4953,8 +4961,8 @@
 			int methodTypeVariablesArity = methodTypeVariables.length;
 			final int factoryArity = classTypeVariablesArity + methodTypeVariablesArity;
 			final LookupEnvironment environment = environment();
-			
-			MethodBinding staticFactory = new SyntheticFactoryMethodBinding(method.original(), environment, originalEnclosingType);
+			MethodBinding targetMethod = isInterface ? new MethodBinding(method.original(), genericType) : method.original();
+			MethodBinding staticFactory = new SyntheticFactoryMethodBinding(targetMethod, environment, originalEnclosingType);
 			staticFactory.typeVariables = new TypeVariableBinding[factoryArity];
 			final SimpleLookupTable map = new SimpleLookupTable(factoryArity);
 			
@@ -5031,7 +5039,7 @@
 			if (staticFactory.thrownExceptions == null) { 
 				staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS;
 			}
-			staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(staticFactory.declaringClass),
+			staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(isInterface ? allocationType : staticFactory.declaringClass),
 																												staticFactory);
 		}
 		if (sfi == 0)
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 20fd791..46d4265 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
@@ -87,7 +91,7 @@
 	public ClassScope scope;
 	protected SourceTypeBinding prototype;
 	LookupEnvironment environment;
-
+	public ModuleBinding module;
 	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
 	// if a new category is added, also increment MAX_SYNTHETICS
 	private final static int METHOD_EMUL = 0;
@@ -1454,7 +1458,13 @@
 public boolean isTaggedRepeatable() {  // tagged but not necessarily repeatable. see isRepeatableAnnotationType.
 	return (this.tagBits & TagBits.AnnotationRepeatable) != 0;
 }
-
+public boolean canBeSeenBy(Scope sco) {
+	SourceTypeBinding invocationType = sco.enclosingSourceType();
+	if (TypeBinding.equalsEquals(invocationType, this)) 
+		return true;
+	return ((this.environment.canTypeBeSeen(this, sco)) &&
+			super.canBeSeenBy(sco));
+}
 public ReferenceBinding[] memberTypes() {
 	if (!isPrototype()) {
 		if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
@@ -1944,7 +1954,8 @@
 		if ((method.tagBits & TagBits.AnnotationSafeVarargs) != 0) {
 			if (!method.isVarargs()) {
 				methodDecl.scope.problemReporter().safeVarargsOnFixedArityMethod(method);
-			} else if (!method.isStatic() && !method.isFinal() && !method.isConstructor()) {
+			} else if (!method.isStatic() && !method.isFinal() && !method.isConstructor() 
+					&& !(sourceLevel >= ClassFileConstants.JDK9 && method.isPrivate())) {
 				methodDecl.scope.problemReporter().safeVarargsOnNonFinalInstanceMethod(method);
 			}
 		} else if (method.parameters != null && method.parameters.length > 0 && method.isVarargs()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337795
@@ -2101,7 +2112,7 @@
 	if (!isPackageInfo) {
 		boolean isInNullnessAnnotationPackage = this.scope.environment().isNullnessAnnotationPackage(pkg);
 		if (pkg.defaultNullness == NO_NULL_DEFAULT && !isInDefaultPkg && !isInNullnessAnnotationPackage && !(this instanceof NestedTypeBinding)) {
-			ReferenceBinding packageInfo = pkg.getType(TypeConstants.PACKAGE_INFO_NAME);
+			ReferenceBinding packageInfo = pkg.getType(TypeConstants.PACKAGE_INFO_NAME, this.scope.module());
 			if (packageInfo == null) {
 				// no pkgInfo - complain
 				this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext);
@@ -2659,4 +2670,7 @@
 		if (this.superclass instanceof SourceTypeBinding)  // should always be true because private super type can only be accessed in same CU
 			((SourceTypeBinding) this.superclass).tagIndirectlyAccessibleMembers();
 }
+public ModuleBinding module() {
+	return this.module;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index 5f76fed..8cfe4b7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -1,9 +1,13 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
@@ -120,11 +124,12 @@
 	long AnnotationForPackage = ASTNode.Bit44L;
 	long AnnotationForTypeUse = ASTNode.Bit54L;
 	long AnnotationForTypeParameter = ASTNode.Bit55L;
+	long AnnotationForModule = ASTNode.Bit62L;
 	long SE7AnnotationTargetMASK = AnnotationForType | AnnotationForField | AnnotationForMethod
 				| AnnotationForParameter | AnnotationForConstructor | AnnotationForLocalVariable
 				| AnnotationForAnnotationType | AnnotationForPackage;
 	long AnnotationTargetMASK = SE7AnnotationTargetMASK | AnnotationTarget
-				| AnnotationForTypeUse | AnnotationForTypeParameter;
+				| AnnotationForTypeUse | AnnotationForTypeParameter | AnnotationForModule;
 	// 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention
 	long AnnotationSourceRetention = ASTNode.Bit45L;
 	long AnnotationClassRetention = ASTNode.Bit46L;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 5f5360a..794d0a4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -102,8 +106,9 @@
     char[] ANONYMOUS_METHOD = "lambda$".toCharArray(); //$NON-NLS-1$
     char[] DESERIALIZE_LAMBDA = "$deserializeLambda$".toCharArray(); //$NON-NLS-1$
     char[] LAMBDA_TYPE = "<lambda>".toCharArray(); //$NON-NLS-1$
-    
-	// jsr308
+    char[] UPPER_MODULE = "MODULE".toCharArray(); //$NON-NLS-1$
+
+    // jsr308
 	char[] TYPE_USE_TARGET  = "TYPE_USE".toCharArray(); //$NON-NLS-1$
 	char[] TYPE_PARAMETER_TARGET = "TYPE_PARAMETER".toCharArray(); //$NON-NLS-1$
     
@@ -319,7 +324,8 @@
 	// ... methods:
 	char[] IS_TRUE = "isTrue".toCharArray(); //$NON-NLS-1$
 	char[] NOT_NULL = "notNull".toCharArray(); //$NON-NLS-1$
-	
+	char[] PROVIDER = "provider".toCharArray(); //$NON-NLS-1$
+
 	char[][] COM_GOOGLE_COMMON_BASE_PRECONDITIONS = new char[][] { 
 			COM, GOOGLE, "common".toCharArray(), "base".toCharArray(), "Preconditions".toCharArray() }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	// ... methods:
@@ -464,4 +470,10 @@
 
 	// synthetic package-info name
 	public static final char[] PACKAGE_INFO_NAME = "package-info".toCharArray(); //$NON-NLS-1$
+	public static final char[] MODULE_INFO_NAME = "module-info".toCharArray(); //$NON-NLS-1$
+	public static final char[] MODULE_INFO_FILE_NAME = "module-info.java".toCharArray(); //$NON-NLS-1$
+	public static final String MODULE_INFO_FILE_NAME_STRING = "module-info.java"; //$NON-NLS-1$
+	public static final String MODULE_INFO_CLASS_NAME_STRING = "module-info.class"; //$NON-NLS-1$
+	// java.base module name
+	char[] JAVA_BASE = "java.base".toCharArray(); //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java
index ed0b252..035e1f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java
@@ -18,4 +18,10 @@
 	   we treat the type annotation as a declarative annotation.
 	*/
 	boolean atConflictScenario(int token);
+	/*
+	 * Return true if the parser is parsing a module declaration. In Java 9, module, requires, exports,
+	 * to, uses, provides, and with are restricted keywords (i.e. they are keywords solely where they
+	 * appear as terminals in ModuleDeclaration, and are identifiers everywhere else)
+	 */
+	boolean isParsingModuleDeclaration();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
index b1fde15..939841b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -148,6 +152,8 @@
 		// since 1.7
 		{},
 		// since 1.8
+		{},
+		// since 9
 		{}
 	};
 	public static final char[][][] INLINE_TAGS = {
@@ -168,6 +174,8 @@
 		// since 1.7
 		{},
 		// since 1.8
+		{},
+		// since 9
 		{}
 	};
 	public final static int INLINE_TAGS_LENGTH = INLINE_TAGS.length;
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 4df2cf5..a2b2d19 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Tom Tromey - patch for readTable(String) as described in http://bugs.eclipse.org/bugs/show_bug.cgi?id=32196
@@ -43,98 +47,7 @@
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
-import org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
-import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
-import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
-import org.eclipse.jdt.internal.compiler.ast.Assignment;
-import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.Block;
-import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
-import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
-import org.eclipse.jdt.internal.compiler.ast.CastExpression;
-import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
-import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
-import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
-import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
-import org.eclipse.jdt.internal.compiler.ast.DoStatement;
-import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
-import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
-import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
-import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldReference;
-import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
-import org.eclipse.jdt.internal.compiler.ast.ForStatement;
-import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
-import org.eclipse.jdt.internal.compiler.ast.IfStatement;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
-import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
-import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Javadoc;
-import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
-import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
-import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
-import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
-import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
-import org.eclipse.jdt.internal.compiler.ast.MessageSend;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.NameReference;
-import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
-import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
-import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
-import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
-import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
-import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Receiver;
-import org.eclipse.jdt.internal.compiler.ast.Reference;
-import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
-import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
-import org.eclipse.jdt.internal.compiler.ast.SuperReference;
-import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
-import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
-import org.eclipse.jdt.internal.compiler.ast.ThisReference;
-import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
-import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
-import org.eclipse.jdt.internal.compiler.ast.TryStatement;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
-import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
@@ -1020,6 +933,7 @@
 protected int valueLambdaNestDepth = -1;
 private int stateStackLengthStack[] = new int[0];
 protected boolean parsingJava8Plus;
+protected boolean parsingJava9Plus;
 protected int unstackedAct = ERROR_ACTION;
 private boolean haltOnSyntaxError = false;
 private boolean tolerateDefaultClassMethods = false;
@@ -1037,6 +951,7 @@
 	this.optimizeStringLiterals = optimizeStringLiterals;
 	initializeScanner();
 	this.parsingJava8Plus = this.options.sourceLevel >= ClassFileConstants.JDK1_8;
+	this.parsingJava9Plus = this.options.sourceLevel >= ClassFileConstants.JDK9;
 	this.astLengthStack = new int[50];
 	this.expressionLengthStack = new int[30];
 	this.typeAnnotationLengthStack = new int[30];
@@ -4786,7 +4701,8 @@
 	
 	boolean isDefault = (md.modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0;
 	boolean isStatic = (md.modifiers & ClassFileConstants.AccStatic) != 0;
-	boolean bodyAllowed = isDefault || isStatic;
+	boolean isPrivate = (md.modifiers & ClassFileConstants.AccPrivate) != 0;
+	boolean bodyAllowed = (this.parsingJava9Plus && isPrivate) || isDefault || isStatic;
 	if (this.parsingJava8Plus) {
 		if (bodyAllowed && hasSemicolonBody) {
 			md.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; // avoid complaints regarding undocumented empty body
@@ -5600,6 +5516,470 @@
 		resetModifiers();
 	}
 }
+protected void consumeInternalCompilationUnitWithModuleDeclaration() {
+	this.compilationUnit.moduleDeclaration = (ModuleDeclaration)this.astStack[this.astPtr--];
+	if (this.compilationUnit.isModuleInfo()) {
+		this.compilationUnit.types = new TypeDeclaration[1];
+		this.compilationUnit.createModuleInfoType(this.compilationUnit.moduleDeclaration);
+	}
+	this.astLengthStack[this.astLengthPtr--] = 0;
+}
+protected void consumeRequiresStatement() {
+	RequiresStatement req = (RequiresStatement) this.astStack[this.astPtr];
+	req.declarationEnd = req.declarationSourceEnd = this.endStatementPosition;
+	// recovery
+	if (this.currentElement instanceof RecoveredModule) {
+		this.lastCheckPoint = req.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.add(req, 0);
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton
+	}
+}
+protected void consumeSingleRequiresModuleName() {
+	ModuleReference impt;
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	RequiresStatement req = new RequiresStatement(impt = new ModuleReference(tokens, positions));
+	if (this.currentToken == TokenNameSEMICOLON){
+		req.declarationSourceEnd = impt.sourceEnd + 1;
+	} else {
+		req.declarationSourceEnd = impt.sourceEnd;
+	}
+	req.declarationEnd = req.declarationSourceEnd;
+	req.modifiersSourceStart = this.intStack[this.intPtr--];
+	req.modifiers |= this.intStack[this.intPtr--];
+	req.sourceStart = req.declarationSourceStart = this.intStack[this.intPtr--];
+	req.sourceEnd = impt.sourceEnd;
+	pushOnAstStack(req);
+	// recovery
+	if (this.currentElement instanceof RecoveredModule){
+		this.lastCheckPoint = req.declarationSourceEnd;
+	}
+}
+protected void consumeExportsStatement() {
+	ExportsStatement expt = (ExportsStatement) this.astStack[this.astPtr];
+	expt.declarationSourceEnd = this.endStatementPosition;
+	expt.declarationEnd = expt.declarationSourceEnd;
+	// recovery
+	if (this.currentElement instanceof RecoveredPackageVisibilityStatement) {
+		this.lastCheckPoint = expt.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.parent;
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true;
+		// used to avoid branching back into the regular automaton
+	}
+}
+protected void consumeExportsHeader() {
+	ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+	impt.bits |= ASTNode.inModule;
+	ExportsStatement expt = new ExportsStatement(impt);
+	expt.declarationSourceStart = this.intStack[this.intPtr--];
+	expt.sourceStart = expt.declarationSourceStart;
+	expt.sourceEnd = impt.sourceEnd;
+	if (this.currentToken == TokenNameSEMICOLON){
+		expt.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		expt.declarationSourceEnd = expt.sourceEnd;
+	}
+	expt.declarationEnd = expt.declarationSourceEnd;
+	this.astStack[this.astPtr] = expt; // replace with ExportsStatement
+	// recovery
+	if (this.currentElement instanceof RecoveredModule) {
+		this.lastCheckPoint = expt.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.add(expt, 0);
+	}
+}
+protected void consumeOpensHeader() {
+	ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+	impt.bits |= ASTNode.inModule;
+	OpensStatement stmt = new OpensStatement(impt);
+	stmt.declarationSourceStart = this.intStack[this.intPtr--];
+	stmt.sourceStart = stmt.declarationSourceStart;
+	stmt.sourceEnd = impt.sourceEnd;
+	if (this.currentToken == TokenNameSEMICOLON){
+		stmt.declarationSourceEnd = this.scanner.currentPosition - 1;
+	} else {
+		stmt.declarationSourceEnd = stmt.sourceEnd;
+	}
+	stmt.declarationEnd = stmt.declarationSourceEnd;
+	this.astStack[this.astPtr] = stmt; // replace with OpensStatement
+	// recovery
+	if (this.currentElement instanceof RecoveredModule) {
+		this.lastCheckPoint = stmt.declarationSourceEnd + 1;
+		this.lastCheckPoint = stmt.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.add(stmt, 0);
+	}
+}
+protected void consumeOpensStatement() {
+	OpensStatement expt = (OpensStatement) this.astStack[this.astPtr];
+	expt.declarationSourceEnd = this.endStatementPosition;
+	expt.declarationEnd = expt.declarationSourceEnd;
+	// recovery
+	if (this.currentElement instanceof RecoveredPackageVisibilityStatement) {
+		this.lastCheckPoint = expt.declarationSourceEnd + 1;
+		this.currentElement = this.currentElement.parent;
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true;
+		// used to avoid branching back into the regular automaton
+	}
+}
+protected void consumeSingleTargetModuleName() {
+	ModuleReference reference;
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	pushOnAstStack(reference = new ModuleReference(tokens, positions));
+
+	// recovery
+	if (this.currentElement != null) {
+		this.lastCheckPoint = reference.sourceEnd + 1;
+	}
+
+}
+protected void consumeTargetModuleList() {
+	int length = this.astLengthStack[this.astLengthPtr--];
+	this.astPtr -= length;
+	PackageVisibilityStatement node = (PackageVisibilityStatement) this.astStack[this.astPtr];
+	if (length > 0) {
+	System.arraycopy(
+		this.astStack,
+		this.astPtr + 1,
+		node.targets = new ModuleReference[length],
+		0,
+		length);
+		node.sourceEnd = node.targets[length - 1].sourceEnd;
+		if (this.currentToken == TokenNameSEMICOLON){
+			node.declarationSourceEnd = node.sourceEnd + 1;
+		} else {
+			node.declarationSourceEnd = node.sourceEnd;
+		}
+	}
+	
+	this.listLength = 0; // reset after having read target modules list
+	// recovery TBD
+	if (this.currentElement != null) { // is recovering
+		this.lastCheckPoint = node.sourceEnd;
+	}
+}
+protected void consumeTargetModuleNameList() {
+	this.listLength++;
+	optimizedConcatNodeLists();
+}
+protected void consumeSinglePkgName() {
+	ImportReference impt;
+	int length;
+	char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+	System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+	pushOnAstStack(impt = new ImportReference(tokens, positions, false, ClassFileConstants.AccDefault));
+
+	// recovery
+	if (this.currentElement instanceof RecoveredModule){
+		this.lastCheckPoint = impt.sourceEnd + 1;
+	}
+}
+protected void consumeUsesStatement() {
+	UsesStatement stmt = (UsesStatement) this.astStack[this.astPtr];
+	stmt.declarationEnd = stmt.declarationSourceEnd = this.endStatementPosition;
+	// recovery
+	if (this.currentElement instanceof RecoveredModule){
+		this.lastCheckPoint = stmt.declarationSourceEnd;
+		this.lastIgnoredToken = -1;
+		this.restartRecovery = true;
+	}
+}
+protected void consumeUsesHeader() {
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+	TypeReference siName = getTypeReference(0);
+	if (siName.annotations != null) {
+		for (int j = 0; j < siName.annotations.length; j++) {
+			Annotation[] qualifierAnnot = siName.annotations[j];
+			if (qualifierAnnot != null && qualifierAnnot.length > 0) {
+				problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
+				siName.annotations[j] = null;
+			}
+		}
+	}
+	UsesStatement stmt = new UsesStatement(siName);
+	if (this.currentToken == TokenNameSEMICOLON){
+		stmt.declarationSourceEnd = siName.sourceEnd + 1;
+	} else {
+		stmt.declarationSourceEnd = siName.sourceEnd;
+	}
+	stmt.declarationEnd = stmt.declarationSourceEnd;
+	stmt.sourceStart = stmt.declarationSourceStart = this.intStack[this.intPtr--];
+	stmt.sourceEnd = siName.sourceEnd;
+	pushOnAstStack(stmt);
+	// recovery
+	if (this.currentElement instanceof RecoveredModule){
+		this.lastCheckPoint = stmt.sourceEnd + 1;
+		this.currentElement = this.currentElement.add(stmt, 0);
+	}
+}
+protected void consumeProvidesInterface() {
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+	TypeReference siName = getTypeReference(0);
+	if (siName.annotations != null) {
+		for (int j = 0; j < siName.annotations.length; j++) {
+			Annotation[] qualifierAnnot = siName.annotations[j];
+			if (qualifierAnnot != null && qualifierAnnot.length > 0) {
+				problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
+				siName.annotations[j] = null;
+			}
+		}
+	}
+	ProvidesStatement ref = new ProvidesStatement();
+	ref.serviceInterface = siName;
+	pushOnAstStack(ref);
+	ref.declarationSourceStart = this.intStack[this.intPtr--];
+	ref.sourceStart = ref.declarationSourceStart;
+	ref.sourceEnd = siName.sourceEnd;
+	ref.declarationSourceEnd = ref.sourceEnd;
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = siName.sourceEnd + 1;
+		this.currentElement = this.currentElement.add(ref, 0);
+		this.lastIgnoredToken = -1;
+	}
+}
+protected void consumeSingleServiceImplName() {
+	pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+	pushOnGenericsLengthStack(0);
+	TypeReference siName = getTypeReference(0);
+	if (siName.annotations != null) {
+		for (int j = 0; j < siName.annotations.length; j++) {
+			Annotation[] qualifierAnnot = siName.annotations[j];
+			if (qualifierAnnot != null && qualifierAnnot.length > 0) {
+				problemReporter().misplacedTypeAnnotations(qualifierAnnot[0], qualifierAnnot[qualifierAnnot.length - 1]);
+				siName.annotations[j] = null;
+			}
+		}
+	}
+	pushOnAstStack(siName);
+	// recovery
+	if (this.currentElement instanceof RecoveredModule) {
+		this.lastCheckPoint = siName.sourceEnd + 1;
+	}
+
+}
+protected void consumeServiceImplNameList() {
+	this.listLength++;
+	optimizedConcatNodeLists();
+}
+protected void consumeProvidesStatement() {
+	ProvidesStatement ref = (ProvidesStatement) this.astStack[this.astPtr];
+	ref.declarationEnd = ref.declarationSourceEnd = this.endStatementPosition;
+	//recovery
+	if (this.currentElement != null) {
+		this.lastIgnoredToken = -1;
+		this.currentElement = this.currentElement.parent;
+		this.restartRecovery = true; // used to avoid branching back into the regular automaton
+	}
+}
+protected void consumeWithClause() {
+	int length = this.astLengthStack[this.astLengthPtr--];
+	this.astPtr -= length;
+
+	ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr];
+	System.arraycopy(
+		this.astStack,
+		this.astPtr + 1,
+		service.implementations = new TypeReference[length],
+		0,
+		length);
+
+	service.sourceEnd = service.implementations[length - 1].sourceEnd;
+
+	if (this.currentToken == TokenNameSEMICOLON){
+		service.declarationSourceEnd = service.sourceEnd + 1;
+	} else {
+		service.declarationSourceEnd = service.sourceEnd;
+	}
+	this.listLength = 0; // reset after having read super-interfaces
+	// recovery
+	if (this.currentElement != null) { // is recovering
+		this.lastCheckPoint = service.declarationSourceEnd;
+	}
+}
+protected void consumeEmptyModuleStatementsOpt() {
+	pushOnAstLengthStack(0);
+}
+protected void consumeModuleStatements() {
+	concatNodeLists();
+}
+protected void consumeModuleModifiers() {
+	checkComment(); // might update modifiers with AccDeprecated
+	// Merge with other modifiers
+	this.intStack[this.intPtr -1] |= this.modifiers;
+	resetModifiers();
+	// Account for the possible presence of annotations as well
+	this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
+}
+protected void consumeModuleHeader() {
+	// ModuleHeader ::= 'module' Name
+	
+	int length;
+	char[][] tokens =
+		new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+	this.identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length);
+	System.arraycopy(
+		this.identifierPositionStack,
+		this.identifierPtr--,
+		positions,
+		0,
+		length);
+
+	ModuleDeclaration typeDecl = new ModuleDeclaration(this.compilationUnit.compilationResult, tokens, positions);
+	//compute the declaration source too
+	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
+	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
+	typeDecl.modifiers = this.intStack[this.intPtr--];
+	if (typeDecl.modifiersSourceStart >= 0) {
+		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
+	}
+//	int otherModifiersStart = this.intStack[this.intPtr--];
+//	int otherModifiers = this.intStack[this.intPtr--];
+//	if (otherModifiersStart >= 0) {
+//		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart = otherModifiersStart;
+//	}
+	// Merge with other modifiers
+//	typeDecl.modifiers |= otherModifiers;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		System.arraycopy(
+			this.expressionStack,
+			(this.expressionPtr -= length) + 1,
+			typeDecl.annotations = new Annotation[length],
+			0,
+			length);
+	}
+	pushOnAstStack(typeDecl);
+
+	this.listLength = 0;
+	// recovery
+	if (this.currentElement != null){
+		this.lastCheckPoint = typeDecl.bodyStart;
+		this.currentElement = this.currentElement.add(typeDecl, 0);
+		this.lastIgnoredToken = -1;
+	}
+		// javadoc
+//		typeDecl.javadoc = this.javadoc;
+//		this.javadoc = null;
+}
+protected void consumeModuleDeclaration() {
+	// ModuleDeclaration ::= ModuleHeader ModuleBody
+	int length = this.astLengthStack[this.astLengthPtr--];
+	int[] flag = new int[length + 1]; //plus one -- see <HERE>
+	int size1 = 0, size2 = 0, size3 = 0, size4 = 0, size5 = 0;
+	if (length != 0) {
+		//there are length declarations
+		//dispatch according to the type of the declarations
+		for (int i = length - 1; i >= 0; i--) {
+			ASTNode astNode = this.astStack[this.astPtr--];
+			if (astNode instanceof RequiresStatement) {
+				flag[i] = 1;
+				size1++;
+			} else if (astNode instanceof ExportsStatement) {
+				flag[i] = 2;
+				size2++;
+			} else if (astNode instanceof UsesStatement) {
+				//field
+				flag[i] = 3;
+				size3++;
+			} else if (astNode instanceof ProvidesStatement){
+				flag[i] = 4;
+				size4++;
+			} else if (astNode instanceof OpensStatement) {
+				flag[i] = 5;
+				size5++;
+			}
+		}
+	}
+	ModuleDeclaration modul = (ModuleDeclaration) this.astStack[this.astPtr];
+	modul.requiresCount = size1;
+	modul.exportsCount = size2;
+	modul.usesCount = size3;
+	modul.servicesCount = size4;
+	modul.opensCount = size5;
+	modul.requires = new RequiresStatement[size1];
+	modul.exports = new ExportsStatement[size2];
+	modul.uses = new UsesStatement[size3];
+	modul.services = new ProvidesStatement[size4];
+	modul.opens = new OpensStatement[size5];
+	//arrays fill up
+	size1 = size2 = size3 = size4 = size5 = 0;
+	int flagI = flag[0], start = 0;
+	int length2;
+	for (int end = 0; end <= length; end++) //<HERE> the plus one allows to
+		{
+		if (flagI != flag[end]) //treat the last element as a ended flag.....
+			{ //array copy
+			switch (flagI) {
+				case 1 :
+					size1 += (length2 = end - start);
+					System.arraycopy(
+						this.astStack,
+						this.astPtr + start + 1,
+						modul.requires,
+						size1 - length2,
+						length2);
+					break;
+				case 2 :
+					size2 += (length2 = end - start);
+					System.arraycopy(
+						this.astStack,
+						this.astPtr + start + 1,
+						modul.exports,
+						size2 - length2,
+						length2);
+					break;
+				case 3 :
+					size3 += (length2 = end - start);
+					System.arraycopy(
+						this.astStack,
+						this.astPtr + start + 1,
+						modul.uses,
+						size3 - length2,
+						length2);
+					break;
+				case 4 :
+					size4 += (length2 = end - start);
+					System.arraycopy(
+						this.astStack,
+						this.astPtr + start + 1,
+						modul.services,
+						size4 - length2,
+						length2);
+					break;
+				case 5 :
+					size5 += (length2 = end - start);
+					System.arraycopy(
+						this.astStack,
+						this.astPtr + start + 1,
+						modul.opens,
+						size5 - length2,
+						length2);
+					break;
+			}
+			flagI = flag[start = end];
+		}
+	}
+	modul.bodyEnd = this.endStatementPosition;
+	modul.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
 protected void consumePackageDeclaration() {
 	// PackageDeclaration ::= 'package' Name ';'
 	/* build an ImportRef build from the last name
@@ -5970,6 +6350,19 @@
 protected void consumeReferenceType3() {
 	pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
 }
+protected void consumeResourceAsLocalVariable() {
+	// Resource ::= Name
+	NameReference ref = getUnspecifiedReference(true);
+	//ref.bits |= ASTNode.IsCapturedOuterLocal;
+	pushOnAstStack(ref);
+ }
+protected void consumeResourceAsFieldAccess() {
+	// Resource ::= FieldAccess
+	FieldReference ref = (FieldReference) this.expressionStack[this.expressionPtr--];
+	//NameReference ref = getUnspecifiedReference(true);
+	//ref.bits |= ASTNode.IsCapturedOuterLocal;
+	pushOnAstStack(ref);
+ }
 protected void consumeResourceAsLocalVariableDeclaration() {
 	// Resource ::= Type PushModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization
 	// Resource ::= Modifiers Type PushRealModifiers VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization
@@ -5980,9 +6373,12 @@
 }
 protected void consumeResourceOptionalTrailingSemiColon(boolean punctuated) {
 	// TrailingSemiColon ::= ';'
-	LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr];
+	Statement statement = (Statement) this.astStack[this.astPtr];
+	
 	if (punctuated) {
-		localDeclaration.declarationSourceEnd = this.endStatementPosition;
+		if (statement instanceof LocalDeclaration) {
+			((LocalDeclaration) statement).declarationSourceEnd = this.endStatementPosition;
+		}
 	}
 }
 protected void consumeRestoreDiet() {
@@ -6171,1806 +6567,1922 @@
 		    consumeEmptyInternalCompilationUnit();  
 			break;
  
-    case 97 : if (DEBUG) { System.out.println("ReduceImports ::="); }  //$NON-NLS-1$
-		    consumeReduceImports();  
+    case 97 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithModuleDeclaration();  
 			break;
  
-    case 98 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); }  //$NON-NLS-1$
-		    consumeEnterCompilationUnit();  
+    case 98 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ModuleDeclaration"); }  //$NON-NLS-1$
+		    consumeInternalCompilationUnitWithModuleDeclaration();  
 			break;
  
-    case 114 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
-		    consumeCatchHeader();  
+    case 99 : if (DEBUG) { System.out.println("ModuleDeclaration ::= ModuleHeader ModuleBody"); }  //$NON-NLS-1$
+		    consumeModuleDeclaration();  
 			break;
  
-    case 116 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); }  //$NON-NLS-1$
-		    consumeImportDeclarations();  
+    case 100 : if (DEBUG) { System.out.println("ModuleHeader ::= Modifiersopt ModuleModifieropt module"); }  //$NON-NLS-1$
+		    consumeModuleHeader();  
 			break;
  
-    case 118 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); }  //$NON-NLS-1$
-		    consumeTypeDeclarations();  
+    case 102 : if (DEBUG) { System.out.println("ModuleModifieropt ::= ModuleModifier"); }  //$NON-NLS-1$
+		    consumeModuleModifiers();  
 			break;
  
-    case 119 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); }  //$NON-NLS-1$
-		    consumePackageDeclaration();  
+    case 105 : if (DEBUG) { System.out.println("ModuleStatementsOpt ::="); }  //$NON-NLS-1$
+		    consumeEmptyModuleStatementsOpt();  
 			break;
  
-    case 120 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); }  //$NON-NLS-1$
-		    consumePackageDeclarationNameWithModifiers();  
+    case 108 : if (DEBUG) { System.out.println("ModuleStatements ::= ModuleStatements ModuleStatement"); }  //$NON-NLS-1$
+		    consumeModuleStatements();  
 			break;
  
-    case 121 : if (DEBUG) { System.out.println("PackageDeclarationName ::= PackageComment package Name"); }  //$NON-NLS-1$
-		    consumePackageDeclarationName();  
+    case 114 : if (DEBUG) { System.out.println("RequiresStatement ::= SingleRequiresModuleName SEMICOLON"); }  //$NON-NLS-1$
+		    consumeRequiresStatement();  
 			break;
  
-    case 122 : if (DEBUG) { System.out.println("PackageComment ::="); }  //$NON-NLS-1$
-		    consumePackageComment();  
+    case 115 : if (DEBUG) { System.out.println("SingleRequiresModuleName ::= requires..."); }  //$NON-NLS-1$
+		    consumeSingleRequiresModuleName();  
 			break;
  
-    case 127 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); }  //$NON-NLS-1$
-		    consumeImportDeclaration();  
+    case 116 : if (DEBUG) { System.out.println("RequiresModifiersopt ::= RequiresModifiers"); }  //$NON-NLS-1$
+		    consumeModifiers();  
 			break;
  
-    case 128 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name..."); }  //$NON-NLS-1$
-		    consumeSingleTypeImportDeclarationName();  
+    case 117 : if (DEBUG) { System.out.println("RequiresModifiersopt ::="); }  //$NON-NLS-1$
+		    consumeDefaultModifiers();  
 			break;
  
-    case 129 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
-		    consumeImportDeclaration();  
-			break;
- 
-    case 130 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); }  //$NON-NLS-1$
-		    consumeTypeImportOnDemandDeclarationName();  
-			break;
- 
-     case 133 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
-		    consumeEmptyTypeDeclaration();  
-			break;
- 
-    case 137 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); }  //$NON-NLS-1$
+    case 119 : if (DEBUG) { System.out.println("RequiresModifiers ::= RequiresModifiers RequiresModifier"); }  //$NON-NLS-1$
 		    consumeModifiers2();  
 			break;
  
-    case 149 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); }  //$NON-NLS-1$
+    case 122 : if (DEBUG) { System.out.println("ExportsStatement ::= ExportsHeader TargetModuleListopt"); }  //$NON-NLS-1$
+		    consumeExportsStatement();  
+			break;
+ 
+    case 123 : if (DEBUG) { System.out.println("ExportsHeader ::= exports SinglePkgName"); }  //$NON-NLS-1$
+		    consumeExportsHeader();  
+			break;
+ 
+    case 125 : if (DEBUG) { System.out.println("TargetModuleListopt ::= to TargetModuleNameList"); }  //$NON-NLS-1$
+		    consumeTargetModuleList();  
+			break;
+ 
+    case 126 : if (DEBUG) { System.out.println("TargetModuleName ::= UnannotatableName"); }  //$NON-NLS-1$
+		    consumeSingleTargetModuleName();  
+			break;
+ 
+    case 128 : if (DEBUG) { System.out.println("TargetModuleNameList ::= TargetModuleNameList COMMA..."); }  //$NON-NLS-1$
+		    consumeTargetModuleNameList();  
+			break;
+ 
+    case 129 : if (DEBUG) { System.out.println("SinglePkgName ::= UnannotatableName"); }  //$NON-NLS-1$
+		    consumeSinglePkgName();  
+			break;
+ 
+    case 130 : if (DEBUG) { System.out.println("OpensStatement ::= OpensHeader TargetModuleListopt..."); }  //$NON-NLS-1$
+		    consumeOpensStatement();  
+			break;
+ 
+    case 131 : if (DEBUG) { System.out.println("OpensHeader ::= opens SinglePkgName"); }  //$NON-NLS-1$
+		    consumeOpensHeader();  
+			break;
+ 
+    case 132 : if (DEBUG) { System.out.println("UsesStatement ::= UsesHeader SEMICOLON"); }  //$NON-NLS-1$
+		    consumeUsesStatement();  
+			break;
+ 
+    case 133 : if (DEBUG) { System.out.println("UsesHeader ::= uses Name"); }  //$NON-NLS-1$
+		    consumeUsesHeader();  
+			break;
+ 
+    case 134 : if (DEBUG) { System.out.println("ProvidesStatement ::= ProvidesInterface WithClause..."); }  //$NON-NLS-1$
+		    consumeProvidesStatement();  
+			break;
+ 
+    case 135 : if (DEBUG) { System.out.println("ProvidesInterface ::= provides Name"); }  //$NON-NLS-1$
+		    consumeProvidesInterface();  
+			break;
+ 
+    case 136 : if (DEBUG) { System.out.println("ServiceImplName ::= Name"); }  //$NON-NLS-1$
+		    consumeSingleServiceImplName();  
+			break;
+ 
+    case 138 : if (DEBUG) { System.out.println("ServiceImplNameList ::= ServiceImplNameList COMMA..."); }  //$NON-NLS-1$
+		    consumeServiceImplNameList();  
+			break;
+ 
+    case 139 : if (DEBUG) { System.out.println("WithClause ::= with ServiceImplNameList"); }  //$NON-NLS-1$
+		    consumeWithClause();  
+			break;
+ 
+    case 140 : if (DEBUG) { System.out.println("ReduceImports ::="); }  //$NON-NLS-1$
+		    consumeReduceImports();  
+			break;
+ 
+    case 141 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); }  //$NON-NLS-1$
+		    consumeEnterCompilationUnit();  
+			break;
+ 
+    case 163 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
+		    consumeCatchHeader();  
+			break;
+ 
+    case 165 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); }  //$NON-NLS-1$
+		    consumeImportDeclarations();  
+			break;
+ 
+    case 167 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); }  //$NON-NLS-1$
+		    consumeTypeDeclarations();  
+			break;
+ 
+    case 168 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); }  //$NON-NLS-1$
+		    consumePackageDeclaration();  
+			break;
+ 
+    case 169 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); }  //$NON-NLS-1$
+		    consumePackageDeclarationNameWithModifiers();  
+			break;
+ 
+    case 170 : if (DEBUG) { System.out.println("PackageDeclarationName ::= PackageComment package Name"); }  //$NON-NLS-1$
+		    consumePackageDeclarationName();  
+			break;
+ 
+    case 171 : if (DEBUG) { System.out.println("PackageComment ::="); }  //$NON-NLS-1$
+		    consumePackageComment();  
+			break;
+ 
+    case 176 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 177 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name..."); }  //$NON-NLS-1$
+		    consumeSingleTypeImportDeclarationName();  
+			break;
+ 
+    case 178 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 179 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); }  //$NON-NLS-1$
+		    consumeTypeImportOnDemandDeclarationName();  
+			break;
+ 
+     case 182 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+		    consumeEmptyTypeDeclaration();  
+			break;
+ 
+    case 186 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); }  //$NON-NLS-1$
+		    consumeModifiers2();  
+			break;
+ 
+    case 198 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); }  //$NON-NLS-1$
 		    consumeAnnotationAsModifier();  
 			break;
  
-    case 150 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); }  //$NON-NLS-1$
+    case 199 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); }  //$NON-NLS-1$
 		    consumeClassDeclaration();  
 			break;
  
-    case 151 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); }  //$NON-NLS-1$
+    case 200 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); }  //$NON-NLS-1$
 		    consumeClassHeader();  
 			break;
  
-    case 152 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); }  //$NON-NLS-1$
+    case 201 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); }  //$NON-NLS-1$
 		    consumeTypeHeaderNameWithTypeParameters();  
 			break;
  
-    case 154 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); }  //$NON-NLS-1$
+    case 203 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); }  //$NON-NLS-1$
 		    consumeClassHeaderName1();  
 			break;
  
-    case 155 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); }  //$NON-NLS-1$
+    case 204 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); }  //$NON-NLS-1$
 		    consumeClassHeaderExtends();  
 			break;
  
-    case 156 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); }  //$NON-NLS-1$
+    case 205 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); }  //$NON-NLS-1$
 		    consumeClassHeaderImplements();  
 			break;
  
-    case 158 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); }  //$NON-NLS-1$
+    case 207 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); }  //$NON-NLS-1$
 		    consumeInterfaceTypeList();  
 			break;
  
-    case 159 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); }  //$NON-NLS-1$
+    case 208 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); }  //$NON-NLS-1$
 		    consumeInterfaceType();  
 			break;
  
-    case 162 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); }  //$NON-NLS-1$
+    case 211 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); }  //$NON-NLS-1$
 		    consumeClassBodyDeclarations();  
 			break;
  
-    case 166 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod..."); }  //$NON-NLS-1$
+    case 215 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod..."); }  //$NON-NLS-1$
 		    consumeClassBodyDeclaration();  
 			break;
  
-    case 167 : if (DEBUG) { System.out.println("Diet ::="); }  //$NON-NLS-1$
+    case 216 : if (DEBUG) { System.out.println("Diet ::="); }  //$NON-NLS-1$
 		    consumeDiet();  
 			break;
 
-    case 168 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod CreateInitializer..."); }  //$NON-NLS-1$
+    case 217 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod CreateInitializer..."); }  //$NON-NLS-1$
 		    consumeClassBodyDeclaration();  
 			break;
  
-    case 169 : if (DEBUG) { System.out.println("CreateInitializer ::="); }  //$NON-NLS-1$
+    case 218 : if (DEBUG) { System.out.println("CreateInitializer ::="); }  //$NON-NLS-1$
 		    consumeCreateInitializer();  
 			break;
 
-    case 176 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+    case 225 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
 		    consumeEmptyTypeDeclaration();  
 			break;
 
-    case 179 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 228 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeFieldDeclaration();  
 			break;
  
-    case 181 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); }  //$NON-NLS-1$
+    case 230 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); }  //$NON-NLS-1$
 		    consumeVariableDeclarators();  
 			break;
  
-    case 184 : if (DEBUG) { System.out.println("EnterVariable ::="); }  //$NON-NLS-1$
+    case 233 : if (DEBUG) { System.out.println("EnterVariable ::="); }  //$NON-NLS-1$
 		    consumeEnterVariable();  
 			break;
  
-    case 185 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); }  //$NON-NLS-1$
+    case 234 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); }  //$NON-NLS-1$
 		    consumeExitVariableWithInitialization();  
 			break;
  
-    case 186 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); }  //$NON-NLS-1$
+    case 235 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); }  //$NON-NLS-1$
 		    consumeExitVariableWithoutInitialization();  
 			break;
  
-    case 187 : if (DEBUG) { System.out.println("ForceNoDiet ::="); }  //$NON-NLS-1$
+    case 236 : if (DEBUG) { System.out.println("ForceNoDiet ::="); }  //$NON-NLS-1$
 		    consumeForceNoDiet();  
 			break;
  
-    case 188 : if (DEBUG) { System.out.println("RestoreDiet ::="); }  //$NON-NLS-1$
+    case 237 : if (DEBUG) { System.out.println("RestoreDiet ::="); }  //$NON-NLS-1$
 		    consumeRestoreDiet();  
 			break;
  
-    case 193 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); }  //$NON-NLS-1$
+    case 242 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); }  //$NON-NLS-1$
 		    // set to true to consume a method with a body
  consumeMethodDeclaration(true, false);  
 			break;
  
-    case 194 : if (DEBUG) { System.out.println("MethodDeclaration ::= DefaultMethodHeader MethodBody"); }  //$NON-NLS-1$
+    case 243 : if (DEBUG) { System.out.println("MethodDeclaration ::= DefaultMethodHeader MethodBody"); }  //$NON-NLS-1$
 		    // set to true to consume a method with a body
  consumeMethodDeclaration(true, true);  
 			break;
  
-    case 195 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); }  //$NON-NLS-1$
+    case 244 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); }  //$NON-NLS-1$
 		    // set to false to consume a method without body
  consumeMethodDeclaration(false, false);  
 			break;
  
-    case 196 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); }  //$NON-NLS-1$
+    case 245 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 197 : if (DEBUG) { System.out.println("DefaultMethodHeader ::= DefaultMethodHeaderName..."); }  //$NON-NLS-1$
+    case 246 : if (DEBUG) { System.out.println("DefaultMethodHeader ::= DefaultMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 198 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); }  //$NON-NLS-1$
+    case 247 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderNameWithTypeParameters(false);  
 			break;
  
-    case 199 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); }  //$NON-NLS-1$
+    case 248 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); }  //$NON-NLS-1$
 		    consumeMethodHeaderName(false);  
 			break;
  
-    case 200 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
+    case 249 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderNameWithTypeParameters(false);  
 			break;
  
-    case 201 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault Type..."); }  //$NON-NLS-1$
+    case 250 : if (DEBUG) { System.out.println("DefaultMethodHeaderName ::= ModifiersWithDefault Type..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderName(false);  
 			break;
  
-    case 202 : if (DEBUG) { System.out.println("ModifiersWithDefault ::= Modifiersopt default..."); }  //$NON-NLS-1$
+    case 251 : if (DEBUG) { System.out.println("ModifiersWithDefault ::= Modifiersopt default..."); }  //$NON-NLS-1$
 		    consumePushCombineModifiers();  
 			break;
  
-    case 203 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); }  //$NON-NLS-1$
+    case 252 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); }  //$NON-NLS-1$
 		    consumeMethodHeaderRightParen();  
 			break;
  
-    case 204 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); }  //$NON-NLS-1$
+    case 253 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); }  //$NON-NLS-1$
 		    consumeMethodHeaderExtendedDims();  
 			break;
  
-    case 205 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); }  //$NON-NLS-1$
+    case 254 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); }  //$NON-NLS-1$
 		    consumeMethodHeaderThrowsClause();  
 			break;
  
-    case 206 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); }  //$NON-NLS-1$
+    case 255 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); }  //$NON-NLS-1$
 		    consumeConstructorHeader();  
 			break;
  
-    case 207 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); }  //$NON-NLS-1$
+    case 256 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); }  //$NON-NLS-1$
 		    consumeConstructorHeaderNameWithTypeParameters();  
 			break;
  
-    case 208 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); }  //$NON-NLS-1$
+    case 257 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); }  //$NON-NLS-1$
 		    consumeConstructorHeaderName();  
 			break;
  
-    case 210 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); }  //$NON-NLS-1$
+    case 259 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); }  //$NON-NLS-1$
 		    consumeFormalParameterList();  
 			break;
  
-    case 211 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 260 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeFormalParameter(false);  
 			break;
  
-    case 212 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 261 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeFormalParameter(true);  
 			break;
  
-    case 213 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type AT308DOTDOTDOT..."); }  //$NON-NLS-1$
+    case 262 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type AT308DOTDOTDOT..."); }  //$NON-NLS-1$
 		    consumeFormalParameter(true);  
 			break;
  
-    case 214 : if (DEBUG) { System.out.println("CatchFormalParameter ::= Modifiersopt CatchType..."); }  //$NON-NLS-1$
+    case 263 : if (DEBUG) { System.out.println("CatchFormalParameter ::= Modifiersopt CatchType..."); }  //$NON-NLS-1$
 		    consumeCatchFormalParameter();  
 			break;
  
-    case 215 : if (DEBUG) { System.out.println("CatchType ::= UnionType"); }  //$NON-NLS-1$
+    case 264 : if (DEBUG) { System.out.println("CatchType ::= UnionType"); }  //$NON-NLS-1$
 		    consumeCatchType();  
 			break;
  
-    case 216 : if (DEBUG) { System.out.println("UnionType ::= Type"); }  //$NON-NLS-1$
+    case 265 : if (DEBUG) { System.out.println("UnionType ::= Type"); }  //$NON-NLS-1$
 		    consumeUnionTypeAsClassType();  
 			break;
  
-    case 217 : if (DEBUG) { System.out.println("UnionType ::= UnionType OR Type"); }  //$NON-NLS-1$
+    case 266 : if (DEBUG) { System.out.println("UnionType ::= UnionType OR Type"); }  //$NON-NLS-1$
 		    consumeUnionType();  
 			break;
  
-    case 219 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); }  //$NON-NLS-1$
+    case 268 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); }  //$NON-NLS-1$
 		    consumeClassTypeList();  
 			break;
  
-    case 220 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); }  //$NON-NLS-1$
+    case 269 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); }  //$NON-NLS-1$
 		    consumeClassTypeElt();  
 			break;
  
-    case 221 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); }  //$NON-NLS-1$
+    case 270 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); }  //$NON-NLS-1$
 		    consumeMethodBody();  
 			break;
  
-    case 222 : if (DEBUG) { System.out.println("NestedMethod ::="); }  //$NON-NLS-1$
+    case 271 : if (DEBUG) { System.out.println("NestedMethod ::="); }  //$NON-NLS-1$
 		    consumeNestedMethod();  
 			break;
  
-    case 223 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); }  //$NON-NLS-1$
+    case 272 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); }  //$NON-NLS-1$
 		    consumeStaticInitializer();  
 			break;
 
-    case 224 : if (DEBUG) { System.out.println("StaticOnly ::= static"); }  //$NON-NLS-1$
+    case 273 : if (DEBUG) { System.out.println("StaticOnly ::= static"); }  //$NON-NLS-1$
 		    consumeStaticOnly();  
 			break;
  
-    case 225 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); }  //$NON-NLS-1$
+    case 274 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); }  //$NON-NLS-1$
 		    consumeConstructorDeclaration() ;  
 			break;
  
-    case 226 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); }  //$NON-NLS-1$
+    case 275 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); }  //$NON-NLS-1$
 		    consumeInvalidConstructorDeclaration() ;  
 			break;
  
-    case 227 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); }  //$NON-NLS-1$
+    case 276 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(0, THIS_CALL);  
 			break;
  
-    case 228 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); }  //$NON-NLS-1$
+    case 277 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL);  
 			break;
  
-    case 229 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); }  //$NON-NLS-1$
+    case 278 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(0,SUPER_CALL);  
 			break;
  
-    case 230 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 279 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL);  
 			break;
  
-    case 231 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); }  //$NON-NLS-1$
+    case 280 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(1, SUPER_CALL);  
 			break;
  
-    case 232 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
+    case 281 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL);  
 			break;
  
-    case 233 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); }  //$NON-NLS-1$
+    case 282 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(2, SUPER_CALL);  
 			break;
  
-    case 234 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
+    case 283 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL);  
 			break;
  
-    case 235 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); }  //$NON-NLS-1$
+    case 284 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(1, THIS_CALL);  
 			break;
  
-    case 236 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
+    case 285 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL);  
 			break;
  
-    case 237 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); }  //$NON-NLS-1$
+    case 286 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocation(2, THIS_CALL);  
 			break;
  
-    case 238 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
+    case 287 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); }  //$NON-NLS-1$
 		    consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL);  
 			break;
  
-    case 239 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); }  //$NON-NLS-1$
+    case 288 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); }  //$NON-NLS-1$
 		    consumeInterfaceDeclaration();  
 			break;
  
-    case 240 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); }  //$NON-NLS-1$
+    case 289 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); }  //$NON-NLS-1$
 		    consumeInterfaceHeader();  
 			break;
  
-    case 241 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); }  //$NON-NLS-1$
+    case 290 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); }  //$NON-NLS-1$
 		    consumeTypeHeaderNameWithTypeParameters();  
 			break;
  
-    case 243 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); }  //$NON-NLS-1$
+    case 292 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); }  //$NON-NLS-1$
 		    consumeInterfaceHeaderName1();  
 			break;
  
-    case 244 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); }  //$NON-NLS-1$
+    case 293 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); }  //$NON-NLS-1$
 		    consumeInterfaceHeaderExtends();  
 			break;
  
-    case 247 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); }  //$NON-NLS-1$
+    case 296 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); }  //$NON-NLS-1$
 		    consumeInterfaceMemberDeclarations();  
 			break;
  
-    case 248 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
+    case 297 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); }  //$NON-NLS-1$
 		    consumeEmptyTypeDeclaration();  
 			break;
  
-    case 250 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); }  //$NON-NLS-1$
+    case 299 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); }  //$NON-NLS-1$
 		    consumeInterfaceMethodDeclaration(false);  
 			break;
  
-    case 251 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= MethodHeader MethodBody"); }  //$NON-NLS-1$
+    case 300 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= MethodHeader MethodBody"); }  //$NON-NLS-1$
 		    consumeInterfaceMethodDeclaration(false);  
 			break;
  
-    case 252 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); }  //$NON-NLS-1$
+    case 301 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= DefaultMethodHeader..."); }  //$NON-NLS-1$
 		    consumeInterfaceMethodDeclaration(true);  
 			break;
  
-    case 253 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
+    case 302 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
 		    consumeInvalidConstructorDeclaration(true);  
 			break;
  
-    case 254 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
+    case 303 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); }  //$NON-NLS-1$
 		    consumeInvalidConstructorDeclaration(false);  
 			break;
  
-    case 265 : if (DEBUG) { System.out.println("PushLeftBrace ::="); }  //$NON-NLS-1$
+    case 314 : if (DEBUG) { System.out.println("PushLeftBrace ::="); }  //$NON-NLS-1$
 		    consumePushLeftBrace();  
 			break;
  
-    case 266 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); }  //$NON-NLS-1$
+    case 315 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); }  //$NON-NLS-1$
 		    consumeEmptyArrayInitializer();  
 			break;
  
-    case 267 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+    case 316 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
 		    consumeArrayInitializer();  
 			break;
  
-    case 268 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+    case 317 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
 		    consumeArrayInitializer();  
 			break;
  
-    case 270 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); }  //$NON-NLS-1$
+    case 319 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); }  //$NON-NLS-1$
 		    consumeVariableInitializers();  
 			break;
  
-    case 271 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); }  //$NON-NLS-1$
+    case 320 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); }  //$NON-NLS-1$
 		    consumeBlock();  
 			break;
  
-    case 272 : if (DEBUG) { System.out.println("OpenBlock ::="); }  //$NON-NLS-1$
+    case 321 : if (DEBUG) { System.out.println("OpenBlock ::="); }  //$NON-NLS-1$
 		    consumeOpenBlock() ;  
 			break;
  
-    case 273 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatement"); }  //$NON-NLS-1$
+    case 322 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatement"); }  //$NON-NLS-1$
 		    consumeBlockStatement() ;  
 			break;
  
-    case 274 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); }  //$NON-NLS-1$
+    case 323 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); }  //$NON-NLS-1$
 		    consumeBlockStatements() ;  
 			break;
  
-    case 281 : if (DEBUG) { System.out.println("BlockStatement ::= InterfaceDeclaration"); }  //$NON-NLS-1$
+    case 330 : if (DEBUG) { System.out.println("BlockStatement ::= InterfaceDeclaration"); }  //$NON-NLS-1$
 		    consumeInvalidInterfaceDeclaration();  
 			break;
  
-    case 282 : if (DEBUG) { System.out.println("BlockStatement ::= AnnotationTypeDeclaration"); }  //$NON-NLS-1$
+    case 331 : if (DEBUG) { System.out.println("BlockStatement ::= AnnotationTypeDeclaration"); }  //$NON-NLS-1$
 		    consumeInvalidAnnotationTypeDeclaration();  
 			break;
  
-    case 283 : if (DEBUG) { System.out.println("BlockStatement ::= EnumDeclaration"); }  //$NON-NLS-1$
+    case 332 : if (DEBUG) { System.out.println("BlockStatement ::= EnumDeclaration"); }  //$NON-NLS-1$
 		    consumeInvalidEnumDeclaration();  
 			break;
  
-    case 284 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); }  //$NON-NLS-1$
+    case 333 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); }  //$NON-NLS-1$
 		    consumeLocalVariableDeclarationStatement();  
 			break;
  
-    case 285 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); }  //$NON-NLS-1$
+    case 334 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); }  //$NON-NLS-1$
 		    consumeLocalVariableDeclaration();  
 			break;
  
-    case 286 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); }  //$NON-NLS-1$
+    case 335 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); }  //$NON-NLS-1$
 		    consumeLocalVariableDeclaration();  
 			break;
  
-    case 287 : if (DEBUG) { System.out.println("PushModifiers ::="); }  //$NON-NLS-1$
+    case 336 : if (DEBUG) { System.out.println("PushModifiers ::="); }  //$NON-NLS-1$
 		    consumePushModifiers();  
 			break;
  
-    case 288 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); }  //$NON-NLS-1$
+    case 337 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); }  //$NON-NLS-1$
 		    consumePushModifiersForHeader();  
 			break;
  
-    case 289 : if (DEBUG) { System.out.println("PushRealModifiers ::="); }  //$NON-NLS-1$
+    case 338 : if (DEBUG) { System.out.println("PushRealModifiers ::="); }  //$NON-NLS-1$
 		    consumePushRealModifiers();  
 			break;
  
-    case 316 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); }  //$NON-NLS-1$
+    case 365 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); }  //$NON-NLS-1$
 		    consumeEmptyStatement();  
 			break;
  
-    case 317 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); }  //$NON-NLS-1$
+    case 366 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); }  //$NON-NLS-1$
 		    consumeStatementLabel() ;  
 			break;
  
-    case 318 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); }  //$NON-NLS-1$
+    case 367 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); }  //$NON-NLS-1$
 		    consumeStatementLabel() ;  
 			break;
  
-    case 319 : if (DEBUG) { System.out.println("Label ::= Identifier"); }  //$NON-NLS-1$
+    case 368 : if (DEBUG) { System.out.println("Label ::= Identifier"); }  //$NON-NLS-1$
 		    consumeLabel() ;  
 			break;
  
-     case 320 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); }  //$NON-NLS-1$
+     case 369 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeExpressionStatement();  
 			break;
  
-    case 329 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 378 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementIfNoElse();  
 			break;
  
-    case 330 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 379 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementIfWithElse();  
 			break;
  
-    case 331 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); }  //$NON-NLS-1$
+    case 380 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementIfWithElse();  
 			break;
  
-    case 332 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 381 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementSwitch() ;  
 			break;
  
-    case 333 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); }  //$NON-NLS-1$
+    case 382 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); }  //$NON-NLS-1$
 		    consumeEmptySwitchBlock() ;  
 			break;
  
-    case 336 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); }  //$NON-NLS-1$
+    case 385 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); }  //$NON-NLS-1$
 		    consumeSwitchBlock() ;  
 			break;
  
-    case 338 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); }  //$NON-NLS-1$
+    case 387 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); }  //$NON-NLS-1$
 		    consumeSwitchBlockStatements() ;  
 			break;
  
-    case 339 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); }  //$NON-NLS-1$
+    case 388 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); }  //$NON-NLS-1$
 		    consumeSwitchBlockStatement() ;  
 			break;
  
-    case 341 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); }  //$NON-NLS-1$
+    case 390 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); }  //$NON-NLS-1$
 		    consumeSwitchLabels() ;  
 			break;
  
-     case 342 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); }  //$NON-NLS-1$
+     case 391 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); }  //$NON-NLS-1$
 		    consumeCaseLabel();  
 			break;
  
-     case 343 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); }  //$NON-NLS-1$
+     case 392 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); }  //$NON-NLS-1$
 		    consumeDefaultLabel();  
 			break;
  
-    case 344 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 393 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementWhile() ;  
 			break;
  
-    case 345 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); }  //$NON-NLS-1$
+    case 394 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementWhile() ;  
 			break;
  
-    case 346 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); }  //$NON-NLS-1$
+    case 395 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementDo() ;  
 			break;
  
-    case 347 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); }  //$NON-NLS-1$
+    case 396 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); }  //$NON-NLS-1$
 		    consumeStatementFor() ;  
 			break;
  
-    case 348 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); }  //$NON-NLS-1$
+    case 397 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); }  //$NON-NLS-1$
 		    consumeStatementFor() ;  
 			break;
  
-    case 349 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); }  //$NON-NLS-1$
+    case 398 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); }  //$NON-NLS-1$
 		    consumeForInit() ;  
 			break;
  
-    case 353 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); }  //$NON-NLS-1$
+    case 402 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); }  //$NON-NLS-1$
 		    consumeStatementExpressionList() ;  
 			break;
  
-    case 354 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); }  //$NON-NLS-1$
+    case 403 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeSimpleAssertStatement() ;  
 			break;
  
-    case 355 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); }  //$NON-NLS-1$
+    case 404 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); }  //$NON-NLS-1$
 		    consumeAssertStatement() ;  
 			break;
  
-    case 356 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); }  //$NON-NLS-1$
+    case 405 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementBreak() ;  
 			break;
  
-    case 357 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); }  //$NON-NLS-1$
+    case 406 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementBreakWithLabel() ;  
 			break;
  
-    case 358 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); }  //$NON-NLS-1$
+    case 407 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementContinue() ;  
 			break;
  
-    case 359 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); }  //$NON-NLS-1$
+    case 408 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementContinueWithLabel() ;  
 			break;
  
-    case 360 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); }  //$NON-NLS-1$
+    case 409 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementReturn() ;  
 			break;
  
-    case 361 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); }  //$NON-NLS-1$
+    case 410 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementThrow();  
 			break;
  
-    case 362 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); }  //$NON-NLS-1$
+    case 411 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementSynchronized();  
 			break;
  
-    case 363 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); }  //$NON-NLS-1$
+    case 412 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); }  //$NON-NLS-1$
 		    consumeOnlySynchronized();  
 			break;
  
-    case 364 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); }  //$NON-NLS-1$
+    case 413 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); }  //$NON-NLS-1$
 		    consumeStatementTry(false, false);  
 			break;
  
-    case 365 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); }  //$NON-NLS-1$
+    case 414 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); }  //$NON-NLS-1$
 		    consumeStatementTry(true, false);  
 			break;
  
-    case 366 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); }  //$NON-NLS-1$
+    case 415 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); }  //$NON-NLS-1$
 		    consumeStatementTry(false, true);  
 			break;
  
-    case 367 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); }  //$NON-NLS-1$
+    case 416 : if (DEBUG) { System.out.println("TryStatementWithResources ::= try ResourceSpecification"); }  //$NON-NLS-1$
 		    consumeStatementTry(true, true);  
 			break;
  
-    case 368 : if (DEBUG) { System.out.println("ResourceSpecification ::= LPAREN Resources ;opt RPAREN"); }  //$NON-NLS-1$
+    case 417 : if (DEBUG) { System.out.println("ResourceSpecification ::= LPAREN Resources ;opt RPAREN"); }  //$NON-NLS-1$
 		    consumeResourceSpecification();  
 			break;
  
-    case 369 : if (DEBUG) { System.out.println(";opt ::="); }  //$NON-NLS-1$
+    case 418 : if (DEBUG) { System.out.println(";opt ::="); }  //$NON-NLS-1$
 		    consumeResourceOptionalTrailingSemiColon(false);  
 			break;
  
-    case 370 : if (DEBUG) { System.out.println(";opt ::= SEMICOLON"); }  //$NON-NLS-1$
+    case 419 : if (DEBUG) { System.out.println(";opt ::= SEMICOLON"); }  //$NON-NLS-1$
 		    consumeResourceOptionalTrailingSemiColon(true);  
 			break;
  
-    case 371 : if (DEBUG) { System.out.println("Resources ::= Resource"); }  //$NON-NLS-1$
+    case 420 : if (DEBUG) { System.out.println("Resources ::= Resource"); }  //$NON-NLS-1$
 		    consumeSingleResource();  
 			break;
  
-    case 372 : if (DEBUG) { System.out.println("Resources ::= Resources TrailingSemiColon Resource"); }  //$NON-NLS-1$
+    case 421 : if (DEBUG) { System.out.println("Resources ::= Resources TrailingSemiColon Resource"); }  //$NON-NLS-1$
 		    consumeMultipleResources();  
 			break;
  
-    case 373 : if (DEBUG) { System.out.println("TrailingSemiColon ::= SEMICOLON"); }  //$NON-NLS-1$
+    case 422 : if (DEBUG) { System.out.println("TrailingSemiColon ::= SEMICOLON"); }  //$NON-NLS-1$
 		    consumeResourceOptionalTrailingSemiColon(true);  
 			break;
  
-    case 374 : if (DEBUG) { System.out.println("Resource ::= Type PushModifiers VariableDeclaratorId..."); }  //$NON-NLS-1$
+    case 423 : if (DEBUG) { System.out.println("Resource ::= Type PushModifiers VariableDeclaratorId..."); }  //$NON-NLS-1$
 		    consumeResourceAsLocalVariableDeclaration();  
 			break;
  
-    case 375 : if (DEBUG) { System.out.println("Resource ::= Modifiers Type PushRealModifiers..."); }  //$NON-NLS-1$
+    case 424 : if (DEBUG) { System.out.println("Resource ::= Modifiers Type PushRealModifiers..."); }  //$NON-NLS-1$
 		    consumeResourceAsLocalVariableDeclaration();  
 			break;
  
-    case 377 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
+    case 425 : if (DEBUG) { System.out.println("Resource ::= Name"); }  //$NON-NLS-1$
+		    consumeResourceAsLocalVariable();  
+			break;
+ 
+    case 426 : if (DEBUG) { System.out.println("Resource ::= FieldAccess"); }  //$NON-NLS-1$
+		    consumeResourceAsFieldAccess();  
+			break;
+ 
+    case 428 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
 		    consumeExitTryBlock();  
 			break;
  
-    case 379 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
+    case 430 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
 		    consumeCatches();  
 			break;
  
-    case 380 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
+    case 431 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
 		    consumeStatementCatch() ;  
 			break;
  
-    case 382 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
+    case 433 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
 		    consumeLeftParen();  
 			break;
  
-    case 383 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
+    case 434 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
 		    consumeRightParen();  
 			break;
  
-    case 388 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
+    case 439 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayThis();  
 			break;
  
-    case 389 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
+    case 440 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArray();  
 			break;
  
-    case 390 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
+    case 441 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayWithName();  
 			break;
  
-    case 393 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
+    case 444 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayNameThis();  
 			break;
  
-    case 394 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); }  //$NON-NLS-1$
+    case 445 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); }  //$NON-NLS-1$
 		    consumeQualifiedSuperReceiver();  
 			break;
  
-    case 395 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
+    case 446 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayName();  
 			break;
  
-    case 396 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
+    case 447 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayArrayType();  
 			break;
  
-    case 397 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
+    case 448 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveArrayType();  
 			break;
  
-    case 398 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
+    case 449 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveType();  
 			break;
  
-    case 404 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
+    case 455 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeArgumentsAndTrunk(false);  
 			break;
  
-    case 405 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
+    case 456 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeArgumentsAndTrunk(true);  
 			break;
  
-    case 406 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); }  //$NON-NLS-1$
+    case 457 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeForm(true);  
 			break;
  
-    case 407 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); }  //$NON-NLS-1$
+    case 458 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeForm(false);  
 			break;
  
-    case 408 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); }  //$NON-NLS-1$
+    case 459 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionGenericTypeForm();  
 			break;
  
-    case 409 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); }  //$NON-NLS-1$
+    case 460 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionPrimaryForm();  
 			break;
  
-    case 410 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); }  //$NON-NLS-1$
+    case 461 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionPrimaryForm();  
 			break;
  
-    case 411 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); }  //$NON-NLS-1$
+    case 462 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionSuperForm();  
 			break;
  
-    case 412 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); }  //$NON-NLS-1$
+    case 463 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyTypeArguments();  
 			break;
  
-    case 414 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); }  //$NON-NLS-1$
+    case 465 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); }  //$NON-NLS-1$
 		    consumeIdentifierOrNew(false);  
 			break;
  
-    case 415 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); }  //$NON-NLS-1$
+    case 466 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); }  //$NON-NLS-1$
 		    consumeIdentifierOrNew(true);  
 			break;
  
-    case 416 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW LambdaBody"); }  //$NON-NLS-1$
+    case 467 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW LambdaBody"); }  //$NON-NLS-1$
 		    consumeLambdaExpression();  
 			break;
  
-    case 417 : if (DEBUG) { System.out.println("NestedLambda ::="); }  //$NON-NLS-1$
+    case 468 : if (DEBUG) { System.out.println("NestedLambda ::="); }  //$NON-NLS-1$
 		    consumeNestedLambda();  
 			break;
  
-    case 418 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); }  //$NON-NLS-1$
+    case 469 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); }  //$NON-NLS-1$
 		    consumeTypeElidedLambdaParameter(false);  
 			break;
  
-    case 424 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); }  //$NON-NLS-1$
+    case 475 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); }  //$NON-NLS-1$
 		    consumeFormalParameterList();  
 			break;
  
-    case 425 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+    case 476 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
 		    consumeTypeElidedLambdaParameter(true);  
 			break;
  
-    case 428 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); }  //$NON-NLS-1$
+    case 479 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); }  //$NON-NLS-1$
 		    consumeElidedLeftBraceAndReturn();  
 			break;
  
-    case 429 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
+    case 480 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
 		    consumeAllocationHeader();  
 			break;
  
-    case 430 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
+    case 481 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionWithTypeArguments();  
 			break;
  
-    case 431 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); }  //$NON-NLS-1$
+    case 482 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpression();  
 			break;
  
-    case 432 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+    case 483 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
 			break;
  
-    case 433 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+    case 484 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualified() ;  
 			break;
  
-    case 434 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+    case 485 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualified() ;  
 			break;
  
-    case 435 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+    case 486 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
 			break;
  
-    case 436 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); }  //$NON-NLS-1$
+    case 487 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); }  //$NON-NLS-1$
 		    consumeEnterInstanceCreationArgumentList();  
 			break;
  
-    case 437 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); }  //$NON-NLS-1$
+    case 488 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionName() ;  
 			break;
  
-    case 438 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); }  //$NON-NLS-1$
+    case 489 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); }  //$NON-NLS-1$
 		    consumeClassBodyopt();  
 			break;
  
-    case 440 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+    case 491 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
 		    consumeEnterAnonymousClassBody(false);  
 			break;
  
-    case 441 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); }  //$NON-NLS-1$
+    case 492 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); }  //$NON-NLS-1$
 		    consumeClassBodyopt();  
 			break;
  
-    case 443 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+    case 494 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
 		    consumeEnterAnonymousClassBody(true);  
 			break;
  
-    case 445 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
+    case 496 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
 		    consumeArgumentList();  
 			break;
  
-    case 446 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
+    case 497 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();  
 			break;
  
-    case 447 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
+    case 498 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();  
 			break;
  
-    case 448 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 499 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();  
 			break;
  
-    case 449 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
+    case 500 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();  
 			break;
  
-    case 450 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 501 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();  
 			break;
  
-    case 451 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 502 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();  
 			break;
  
-    case 453 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
+    case 504 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExprs();  
 			break;
  
-     case 455 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); }  //$NON-NLS-1$
+     case 506 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExpr();  
 			break;
  
-     case 456 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
+     case 507 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
 		    consumeDims();  
 			break;
  
-     case 459 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 510 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeOneDimLoop(false);  
 			break;
  
-     case 460 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 511 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeOneDimLoop(true);  
 			break;
  
-    case 461 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
+    case 512 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(false);  
 			break;
  
-    case 462 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
+    case 513 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(true);  
 			break;
  
-    case 463 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); }  //$NON-NLS-1$
+    case 514 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(false);  
 			break;
  
-    case 464 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+    case 515 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
 		    consumeMethodInvocationName();  
 			break;
  
-    case 465 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 516 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationNameWithTypeArguments();  
 			break;
  
-    case 466 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 517 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimaryWithTypeArguments();  
 			break;
  
-    case 467 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 518 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimary();  
 			break;
  
-    case 468 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
+    case 519 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimary();  
 			break;
  
-    case 469 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
+    case 520 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimaryWithTypeArguments();  
 			break;
  
-    case 470 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 521 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuperWithTypeArguments();  
 			break;
  
-    case 471 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 522 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuper();  
 			break;
  
-    case 472 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
+    case 523 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
 		    consumeArrayAccess(true);  
 			break;
  
-    case 473 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
+    case 524 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);  
 			break;
  
-    case 474 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
+    case 525 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);  
 			break;
  
-    case 476 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
+    case 527 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
 		    consumePostfixExpression();  
 			break;
  
-    case 479 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
+    case 530 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,true);  
 			break;
  
-    case 480 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
+    case 531 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,true);  
 			break;
  
-    case 481 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
+    case 532 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
 		    consumePushPosition();  
 			break;
  
-    case 484 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 535 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 485 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 536 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 487 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
+    case 538 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,false);  
 			break;
  
-    case 488 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
+    case 539 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,false);  
 			break;
  
-    case 490 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
+    case 541 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
 			break;
  
-    case 491 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
+    case 542 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.NOT);  
 			break;
  
-    case 493 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
+    case 544 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithPrimitiveType();  
 			break;
  
-    case 494 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 545 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithGenericsArray();  
 			break;
  
-    case 495 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 546 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithQualifiedGenericsArray();  
 			break;
  
-    case 496 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
+    case 547 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionLL1();  
 			break;
  
-    case 497 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); }  //$NON-NLS-1$
+    case 548 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionLL1WithBounds();  
 			break;
  
-    case 498 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); }  //$NON-NLS-1$
+    case 549 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithNameArray();  
 			break;
  
-    case 499 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); }  //$NON-NLS-1$
+    case 550 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); }  //$NON-NLS-1$
 		    consumeZeroAdditionalBounds();  
 			break;
  
-    case 503 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
+    case 554 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
 		    consumeOnlyTypeArgumentsForCastExpression();  
 			break;
  
-    case 504 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
+    case 555 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpression();  
 			break;
  
-    case 505 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
+    case 556 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionLL1();  
 			break;
  
-    case 506 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); }  //$NON-NLS-1$
+    case 557 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionLL1WithBounds ();  
 			break;
  
-    case 507 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
+    case 558 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionWithQualifiedGenerics();  
 			break;
  
-    case 509 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 560 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
 			break;
  
-    case 510 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 561 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.DIVIDE);  
 			break;
  
-    case 511 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 562 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.REMAINDER);  
 			break;
  
-    case 513 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
+    case 564 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 514 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
+    case 565 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 516 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
+    case 567 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
 			break;
  
-    case 517 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
+    case 568 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
 			break;
  
-    case 518 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 569 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
 			break;
  
-    case 520 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
+    case 571 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS);  
 			break;
  
-    case 521 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
+    case 572 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER);  
 			break;
  
-    case 522 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
+    case 573 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
 			break;
  
-    case 523 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
+    case 574 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
 			break;
  
-    case 525 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); }  //$NON-NLS-1$
+    case 576 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); }  //$NON-NLS-1$
 		    consumeInstanceOfExpression();  
 			break;
  
-    case 527 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
+    case 578 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
 			break;
  
-    case 528 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
+    case 579 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
 			break;
  
-    case 530 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
+    case 581 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND);  
 			break;
  
-    case 532 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
+    case 583 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.XOR);  
 			break;
  
-    case 534 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
+    case 585 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR);  
 			break;
  
-    case 536 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
+    case 587 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND_AND);  
 			break;
  
-    case 538 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+    case 589 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR_OR);  
 			break;
  
-    case 540 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+    case 591 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
 			break;
  
-    case 543 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
+    case 594 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
 		    consumeAssignment();  
 			break;
  
-    case 545 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
+    case 596 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
 		    ignoreExpressionAssignment(); 
 			break;
  
-    case 546 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
+    case 597 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(EQUAL);  
 			break;
  
-    case 547 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
+    case 598 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(MULTIPLY);  
 			break;
  
-    case 548 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
+    case 599 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(DIVIDE);  
 			break;
  
-    case 549 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
+    case 600 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(REMAINDER);  
 			break;
  
-    case 550 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
+    case 601 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(PLUS);  
 			break;
  
-    case 551 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
+    case 602 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(MINUS);  
 			break;
  
-    case 552 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 603 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(LEFT_SHIFT);  
 			break;
  
-    case 553 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 604 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(RIGHT_SHIFT);  
 			break;
  
-    case 554 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 605 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
 			break;
  
-    case 555 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
+    case 606 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(AND);  
 			break;
  
-    case 556 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
+    case 607 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(XOR);  
 			break;
  
-    case 557 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
+    case 608 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(OR);  
 			break;
  
-    case 558 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); }  //$NON-NLS-1$
+    case 609 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); }  //$NON-NLS-1$
 		    consumeExpression();  
 			break;
  
-    case 561 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
+    case 612 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyExpression();  
 			break;
  
-    case 566 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 617 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyClassBodyDeclarationsopt();  
 			break;
  
-    case 567 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+    case 618 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeClassBodyDeclarationsopt();  
 			break;
  
-     case 568 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
+     case 619 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
 		    consumeDefaultModifiers();  
 			break;
  
-    case 569 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
+    case 620 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
 		    consumeModifiers();  
 			break;
  
-    case 570 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
+    case 621 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyBlockStatementsopt();  
 			break;
  
-     case 572 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
+     case 623 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyDimsopt();  
 			break;
  
-     case 574 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
+     case 625 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyArgumentListopt();  
 			break;
  
-    case 578 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
+    case 629 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
 		    consumeFormalParameterListopt();  
 			break;
  
-     case 582 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+     case 633 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyInterfaceMemberDeclarationsopt();  
 			break;
  
-     case 583 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+     case 634 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeInterfaceMemberDeclarationsopt();  
 			break;
  
-    case 584 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
+    case 635 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
 		    consumeNestedType();  
 			break;
 
-     case 585 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
+     case 636 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyForInitopt();  
 			break;
  
-     case 587 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
+     case 638 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyForUpdateopt();  
 			break;
  
-     case 591 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
+     case 642 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyCatchesopt();  
 			break;
  
-     case 593 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
+     case 644 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
 		    consumeEnumDeclaration();  
 			break;
  
-     case 594 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
+     case 645 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
 		    consumeEnumHeader();  
 			break;
  
-     case 595 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
+     case 646 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
 		    consumeEnumHeaderName();  
 			break;
  
-     case 596 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); }  //$NON-NLS-1$
+     case 647 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); }  //$NON-NLS-1$
 		    consumeEnumHeaderNameWithTypeParameters();  
 			break;
  
-     case 597 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
+     case 648 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
 		    consumeEnumBodyNoConstants();  
 			break;
  
-     case 598 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
+     case 649 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
 		    consumeEnumBodyNoConstants();  
 			break;
  
-     case 599 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
+     case 650 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
 		    consumeEnumBodyWithConstants();  
 			break;
  
-     case 600 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
+     case 651 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
 		    consumeEnumBodyWithConstants();  
 			break;
  
-    case 602 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
+    case 653 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
 		    consumeEnumConstants();  
 			break;
  
-    case 603 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+    case 654 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
 		    consumeEnumConstantHeaderName();  
 			break;
  
-    case 604 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
+    case 655 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
 		    consumeEnumConstantHeader();  
 			break;
  
-    case 605 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
+    case 656 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
 		    consumeEnumConstantWithClassBody();  
 			break;
  
-    case 606 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
+    case 657 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
 		    consumeEnumConstantNoClassBody();  
 			break;
  
-    case 607 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+    case 658 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
 		    consumeArguments();  
 			break;
  
-    case 608 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
+    case 659 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyArguments();  
 			break;
  
-    case 610 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
+    case 661 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
 		    consumeEnumDeclarations();  
 			break;
  
-    case 611 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 662 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyEnumDeclarations();  
 			break;
  
-    case 613 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
+    case 664 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatement();  
 			break;
  
-    case 614 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
+    case 665 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatement();  
 			break;
  
-    case 615 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
+    case 666 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeaderInit(false);  
 			break;
  
-    case 616 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
+    case 667 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeaderInit(true);  
 			break;
  
-    case 617 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
+    case 668 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeader();  
 			break;
  
-    case 618 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
+    case 669 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeImportDeclaration();  
 			break;
  
-    case 619 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
+    case 670 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
 		    consumeSingleStaticImportDeclarationName();  
 			break;
  
-    case 620 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
+    case 671 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeImportDeclaration();  
 			break;
  
-    case 621 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
+    case 672 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
 		    consumeStaticImportOnDemandDeclarationName();  
 			break;
  
-    case 622 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+    case 673 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
 		    consumeTypeArguments();  
 			break;
  
-    case 623 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+    case 674 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
 		    consumeOnlyTypeArguments();  
 			break;
  
-    case 625 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 676 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList1();  
 			break;
  
-    case 627 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
+    case 678 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
 		    consumeTypeArgumentList();  
 			break;
  
-    case 628 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
+    case 679 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
 		    consumeTypeArgument();  
 			break;
  
-    case 632 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
+    case 683 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
 		    consumeReferenceType1();  
 			break;
  
-    case 633 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+    case 684 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentReferenceType1();  
 			break;
  
-    case 635 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 686 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList2();  
 			break;
  
-    case 638 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 689 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeReferenceType2();  
 			break;
  
-    case 639 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+    case 690 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentReferenceType2();  
 			break;
  
-    case 641 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 692 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList3();  
 			break;
  
-    case 644 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 695 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeReferenceType3();  
 			break;
  
-    case 645 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); }  //$NON-NLS-1$
+    case 696 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); }  //$NON-NLS-1$
 		    consumeWildcard();  
 			break;
  
-    case 646 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); }  //$NON-NLS-1$
+    case 697 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); }  //$NON-NLS-1$
 		    consumeWildcardWithBounds();  
 			break;
  
-    case 647 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
+    case 698 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
 		    consumeWildcardBoundsExtends();  
 			break;
  
-    case 648 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
+    case 699 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
 		    consumeWildcardBoundsSuper();  
 			break;
  
-    case 649 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); }  //$NON-NLS-1$
+    case 700 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); }  //$NON-NLS-1$
 		    consumeWildcard1();  
 			break;
  
-    case 650 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 701 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard1WithBounds();  
 			break;
  
-    case 651 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
+    case 702 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
 		    consumeWildcardBounds1Extends();  
 			break;
  
-    case 652 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
+    case 703 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
 		    consumeWildcardBounds1Super();  
 			break;
  
-    case 653 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 704 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeWildcard2();  
 			break;
  
-    case 654 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 705 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard2WithBounds();  
 			break;
  
-    case 655 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
+    case 706 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
 		    consumeWildcardBounds2Extends();  
 			break;
  
-    case 656 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
+    case 707 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
 		    consumeWildcardBounds2Super();  
 			break;
  
-    case 657 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 708 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard3();  
 			break;
  
-    case 658 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 709 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard3WithBounds();  
 			break;
  
-    case 659 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
+    case 710 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
 		    consumeWildcardBounds3Extends();  
 			break;
  
-    case 660 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
+    case 711 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
 		    consumeWildcardBounds3Super();  
 			break;
  
-    case 661 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); }  //$NON-NLS-1$
+    case 712 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); }  //$NON-NLS-1$
 		    consumeTypeParameterHeader();  
 			break;
  
-    case 662 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
+    case 713 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
 		    consumeTypeParameters();  
 			break;
  
-    case 664 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+    case 715 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeParameterList();  
 			break;
  
-    case 666 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 717 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameterWithExtends();  
 			break;
  
-    case 667 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 718 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameterWithExtendsAndBounds();  
 			break;
  
-    case 669 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+    case 720 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
 		    consumeAdditionalBoundList();  
 			break;
  
-    case 670 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
+    case 721 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
 		    consumeAdditionalBound();  
 			break;
  
-    case 672 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+    case 723 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeParameterList1();  
 			break;
  
-    case 673 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
+    case 724 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
 		    consumeTypeParameter1();  
 			break;
  
-    case 674 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 725 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameter1WithExtends();  
 			break;
  
-    case 675 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 726 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameter1WithExtendsAndBounds();  
 			break;
  
-    case 677 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+    case 728 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
 		    consumeAdditionalBoundList1();  
 			break;
  
-    case 678 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
+    case 729 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
 		    consumeAdditionalBound1();  
 			break;
  
-    case 684 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
+    case 735 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 685 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
+    case 736 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 688 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
+    case 739 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
 			break;
  
-    case 689 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
+    case 740 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.NOT);  
 			break;
  
-    case 692 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 743 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
 			break;
  
-    case 693 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
+    case 744 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.MULTIPLY);  
 			break;
  
-    case 694 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 745 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.DIVIDE);  
 			break;
  
-    case 695 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
+    case 746 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.DIVIDE);  
 			break;
  
-    case 696 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 747 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.REMAINDER);  
 			break;
  
-    case 697 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
+    case 748 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.REMAINDER);  
 			break;
  
-    case 699 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 750 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 700 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
+    case 751 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.PLUS);  
 			break;
  
-    case 701 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 752 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 702 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
+    case 753 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.MINUS);  
 			break;
  
-    case 704 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 755 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
 			break;
  
-    case 705 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
+    case 756 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT);  
 			break;
  
-    case 706 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 757 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
 			break;
  
-    case 707 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
+    case 758 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT);  
 			break;
  
-    case 708 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 759 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
 			break;
  
-    case 709 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); }  //$NON-NLS-1$
+    case 760 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
 			break;
  
-    case 711 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+    case 762 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS);  
 			break;
  
-    case 712 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
+    case 763 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LESS);  
 			break;
  
-    case 713 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+    case 764 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER);  
 			break;
  
-    case 714 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
+    case 765 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.GREATER);  
 			break;
  
-    case 715 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 766 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
 			break;
  
-    case 716 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
+    case 767 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL);  
 			break;
  
-    case 717 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 768 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
 			break;
  
-    case 718 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
+    case 769 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL);  
 			break;
  
-    case 720 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); }  //$NON-NLS-1$
+    case 771 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); }  //$NON-NLS-1$
 		    consumeInstanceOfExpressionWithName();  
 			break;
  
-    case 721 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 772 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeInstanceOfExpression();  
 			break;
  
-    case 723 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 774 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
 			break;
  
-    case 724 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
+    case 775 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL);  
 			break;
  
-    case 725 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 776 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
 			break;
  
-    case 726 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
+    case 777 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL);  
 			break;
  
-    case 728 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
+    case 779 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND);  
 			break;
  
-    case 729 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
+    case 780 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.AND);  
 			break;
  
-    case 731 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 782 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.XOR);  
 			break;
  
-    case 732 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); }  //$NON-NLS-1$
+    case 783 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.XOR);  
 			break;
  
-    case 734 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 785 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR);  
 			break;
  
-    case 735 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
+    case 786 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.OR);  
 			break;
  
-    case 737 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 788 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND_AND);  
 			break;
  
-    case 738 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
+    case 789 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.AND_AND);  
 			break;
  
-    case 740 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 791 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR_OR);  
 			break;
  
-    case 741 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
+    case 792 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.OR_OR);  
 			break;
  
-    case 743 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 794 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
 			break;
  
-    case 744 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
+    case 795 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
 		    consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ;  
 			break;
  
-    case 748 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
+    case 799 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;  
 			break;
  
-    case 749 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
+    case 800 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ;  
 			break;
  
-    case 750 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+    case 801 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ;  
 			break;
  
-    case 751 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+    case 802 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;  
 			break;
  
-    case 752 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
+    case 803 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeader() ;  
 			break;
  
-    case 753 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
+    case 804 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclaration() ;  
 			break;
  
-    case 755 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 806 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyAnnotationTypeMemberDeclarationsopt() ;  
 			break;
  
-    case 756 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+    case 807 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarationsopt() ;  
 			break;
  
-    case 758 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
+    case 809 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarations() ;  
 			break;
  
-    case 759 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 810 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderNameWithTypeParameters(true);  
 			break;
  
-    case 760 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 811 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderName(true);  
 			break;
  
-    case 761 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
+    case 812 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMethodHeaderDefaultValue() ;  
 			break;
  
-    case 762 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
+    case 813 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
 		    consumeMethodHeaderDefaultValue();  
 			break;
  
-    case 763 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); }  //$NON-NLS-1$
+    case 814 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 764 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
+    case 815 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclaration() ;  
 			break;
  
-    case 772 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); }  //$NON-NLS-1$
+    case 823 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); }  //$NON-NLS-1$
 		    consumeAnnotationName() ;  
 			break;
  
-    case 773 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 824 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeNormalAnnotation(false) ;  
 			break;
  
-    case 774 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
+    case 825 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMemberValuePairsopt() ;  
 			break;
  
-    case 777 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
+    case 828 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
 		    consumeMemberValuePairs() ;  
 			break;
  
-    case 778 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); }  //$NON-NLS-1$
+    case 829 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); }  //$NON-NLS-1$
 		    consumeMemberValuePair() ;  
 			break;
  
-    case 779 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
+    case 830 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
 		    consumeEnterMemberValue() ;  
 			break;
  
-    case 780 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
+    case 831 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
 		    consumeExitMemberValue() ;  
 			break;
  
-    case 782 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
+    case 833 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
 		    consumeMemberValueAsName() ;  
 			break;
  
-    case 785 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
+    case 836 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeMemberValueArrayInitializer() ;  
 			break;
  
-    case 786 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
+    case 837 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeMemberValueArrayInitializer() ;  
 			break;
  
-    case 787 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
+    case 838 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeEmptyMemberValueArrayInitializer() ;  
 			break;
  
-    case 788 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
+    case 839 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeEmptyMemberValueArrayInitializer() ;  
 			break;
  
-    case 789 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); }  //$NON-NLS-1$
+    case 840 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); }  //$NON-NLS-1$
 		    consumeEnterMemberValueArrayInitializer() ;  
 			break;
  
-    case 791 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
+    case 842 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
 		    consumeMemberValues() ;  
 			break;
  
-    case 792 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
+    case 843 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
 		    consumeMarkerAnnotation(false) ;  
 			break;
  
-    case 793 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); }  //$NON-NLS-1$
+    case 844 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); }  //$NON-NLS-1$
 		    consumeSingleMemberAnnotationMemberValue() ;  
 			break;
  
-    case 794 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 845 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeSingleMemberAnnotation(false) ;  
 			break;
  
-    case 795 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); }  //$NON-NLS-1$
+    case 846 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderNameWithTypeParameters();  
 			break;
  
-    case 796 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 847 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderName();  
 			break;
  
-    case 797 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
+    case 848 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderNameWithTypeParameters();  
 			break;
  
-    case 798 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); }  //$NON-NLS-1$
+    case 849 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderName();  
 			break;
  
-    case 799 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+    case 850 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 800 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+    case 851 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
@@ -8753,16 +9265,26 @@
 	if (hasResources) {
 		// get the resources
 		length = this.astLengthStack[this.astLengthPtr--];
-		LocalDeclaration[] resources = new LocalDeclaration[length];
+		Statement[] stmts  = new Statement[length];
 		System.arraycopy(
-				this.astStack,
-				(this.astPtr -= length) + 1,
-				resources,
-				0,
-				length);
-		tryStmt.resources = resources;
+		this.astStack,
+		(this.astPtr -= length) + 1,
+		stmts,
+		0,
+		length);
+
+		tryStmt.resources = stmts;
+			
 		if (this.options.sourceLevel < ClassFileConstants.JDK1_7) {
-			problemReporter().autoManagedResourcesNotBelow17(resources);
+			problemReporter().autoManagedResourcesNotBelow17(stmts);
+		}
+		if (this.options.sourceLevel < ClassFileConstants.JDK9) {
+			for (int i = 0, l = stmts.length; i < l; ++i) {
+				Statement stmt = stmts[i];
+				if (stmt instanceof FieldReference || stmt instanceof NameReference) {
+					problemReporter().autoManagedVariableResourcesNotBelow9((Expression) stmt);
+				}
+			}
 		}
 	}
 	//positions
@@ -8952,6 +9474,10 @@
 			checkAndSetModifiers(ClassFileConstants.AccNative);
 			pushOnExpressionStackLengthStack(0);
 			break;
+		case TokenNameopen :
+			checkAndSetModifiers(ClassFileConstants.ACC_OPEN);
+			pushOnExpressionStackLengthStack(0);
+			break;
 		case TokenNameprivate :
 			checkAndSetModifiers(ClassFileConstants.AccPrivate);
 			pushOnExpressionStackLengthStack(0);
@@ -8968,12 +9494,19 @@
 			checkAndSetModifiers(ClassFileConstants.AccTransient);
 			pushOnExpressionStackLengthStack(0);
 			break;
+		case TokenNametransitive :
+			checkAndSetModifiers(ClassFileConstants.ACC_TRANSITIVE);
+			pushOnExpressionStackLengthStack(0);
+			break;
 		case TokenNamevolatile :
 			checkAndSetModifiers(ClassFileConstants.AccVolatile);
 			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamestatic :
-			checkAndSetModifiers(ClassFileConstants.AccStatic);
+			if (isParsingModuleDeclaration())
+				checkAndSetModifiers(ClassFileConstants.ACC_STATIC_PHASE);
+			else
+				checkAndSetModifiers(ClassFileConstants.AccStatic);
 			pushOnExpressionStackLengthStack(0);
 			break;
 		case TokenNamesynchronized :
@@ -9122,6 +9655,12 @@
 		case TokenNamecontinue :
 		case TokenNamereturn :
 		case TokenNamecase :
+		case TokenNamemodule:
+		case TokenNamerequires:
+		case TokenNameexports:
+		case TokenNameopens:
+		case TokenNameuses:
+		case TokenNameprovides:
 			pushOnIntStack(this.scanner.startPosition);
 			break;
 		case TokenNamenew :
@@ -11808,7 +12347,7 @@
 	}
 	this.identifierLengthStack[this.identifierLengthPtr] = 1;
 	if (this.parsingJava8Plus && identifier.length == 1 && identifier[0] == '_' && !this.processingLambdaParameterList) {
-		problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, false /* not a lambda parameter */);
+		problemReporter().illegalUseOfUnderscoreAsAnIdentifier((int) (position >>> 32), (int) position, this.parsingJava9Plus);
 	}
 }
 protected void pushIdentifier() {
@@ -12636,4 +13175,9 @@
 		return lastAction != ERROR_ACTION;
 	}
 }
+@Override
+public boolean isParsingModuleDeclaration() {
+	// It can be a null in case of a Vanguard parser, which means no module to be dealt with.
+	return (this.compilationUnit != null && this.compilationUnit.isModuleInfo());
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index 50dce29..f3bfae0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -13,24 +13,25 @@
 /*An interface that contains static declarations for some basic information
  about the parser such as the number of rules in the grammar, the starting state, etc...*/
 public interface ParserBasicInformation {
-    public final static int
 
-      ERROR_SYMBOL      = 118,
-      MAX_NAME_LENGTH   = 41,
-      NUM_STATES        = 1102,
+	public final static int
 
-      NT_OFFSET         = 118,
-      SCOPE_UBOUND      = 290,
-      SCOPE_SIZE        = 291,
-      LA_STATE_OFFSET   = 16382,
-      MAX_LA            = 1,
-      NUM_RULES         = 800,
-      NUM_TERMINALS     = 118,
-      NUM_NON_TERMINALS = 360,
-      NUM_SYMBOLS       = 478,
-      START_STATE       = 1580,
-      EOFT_SYMBOL       = 60,
-      EOLT_SYMBOL       = 60,
-      ACCEPT_ACTION     = 16381,
-      ERROR_ACTION      = 16382;
+	ERROR_SYMBOL = 128,
+					MAX_NAME_LENGTH = 41,
+					NUM_STATES = 1152,
+
+					NT_OFFSET = 128,
+					SCOPE_UBOUND = 290,
+					SCOPE_SIZE = 291,
+					LA_STATE_OFFSET = 16451,
+					MAX_LA = 1,
+					NUM_RULES = 851,
+					NUM_TERMINALS = 128,
+					NUM_NON_TERMINALS = 388,
+					NUM_SYMBOLS = 516,
+					START_STATE = 895,
+					EOFT_SYMBOL = 60,
+					EOLT_SYMBOL = 60,
+					ACCEPT_ACTION = 16450,
+					ERROR_ACTION = 16451;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
index ac1c1e5..c03f87b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -20,6 +24,8 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleStatement;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.util.Util;
@@ -73,6 +79,17 @@
 	return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
 }
 /*
+ *	Record an e reference
+ */
+public RecoveredElement add(ModuleStatement moduleStatement, int bracketBalanceValue){
+
+	/* default behavior is to delegate recording to parent if any */
+	resetPendingModifiers();
+	if (this.parent == null) return this; // ignore
+	this.updateSourceEndIfNecessary(previousAvailableLineEnd(moduleStatement.declarationSourceStart - 1));
+	return this.parent.add(moduleStatement, bracketBalanceValue);
+}
+/*
  * Record a field declaration
  */
 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
@@ -125,6 +142,12 @@
 	this.updateSourceEndIfNecessary(previousAvailableLineEnd(statement.sourceStart - 1));
 	return this.parent.add(statement, bracketBalanceValue);
 }
+public RecoveredElement add(ModuleDeclaration moduleDeclaration, int bracketBalanceValue){
+	resetPendingModifiers();
+	if (this.parent == null) return this; // ignore
+	this.updateSourceEndIfNecessary(previousAvailableLineEnd(moduleDeclaration.declarationSourceStart - 1));
+	return this.parent.add(moduleDeclaration, bracketBalanceValue);
+}
 /*
  *	Record a type declaration
  */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java
new file mode 100644
index 0000000..3826d04
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExport.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+
+public class RecoveredExport extends RecoveredElement {
+
+	public ExportsStatement exportReference;
+	RecoveredModuleReference[] targets;
+	int targetCount = 0;
+	
+	public RecoveredExport(ExportsStatement exportReference, RecoveredElement parent, int bracketBalance) {
+		super(parent, bracketBalance);
+		this.exportReference = exportReference;
+	}
+	public RecoveredElement add(ModuleReference target,  int bracketBalance1) {
+
+		if (this.targets == null) {
+			this.targets = new RecoveredModuleReference[5];
+			this.targetCount = 0;
+		} else {
+			if (this.targetCount == this.targets.length) {
+				System.arraycopy(
+					this.targets,
+					0,
+					(this.targets = new RecoveredModuleReference[2 * this.targetCount]),
+					0,
+					this.targetCount);
+			}
+		}
+		RecoveredModuleReference element = new RecoveredModuleReference(target, this, bracketBalance1);
+		this.targets[this.targetCount++] = element;
+
+		/* if target not finished, then target becomes current */
+		if (target.sourceEnd == 0) return element;
+		return this;
+		
+	}
+	/*
+	 * Answer the associated parsed structure
+	 */
+	public ASTNode parseTree(){
+		return this.exportReference;
+	}
+	/*
+	 * Answer the very source end of the corresponding parse node
+	 */
+	public int sourceEnd(){
+		return this.exportReference.declarationSourceEnd;
+	}
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered export: " + this.exportReference.toString(); //$NON-NLS-1$
+	}
+	public ExportsStatement updatedExportReference(){
+		if (this.targetCount > 0) {
+			int existingCount = this.exportReference.targets != null ? this.exportReference.targets.length : 0, actualCount = 0;
+			ModuleReference[] moduleRef1 = new ModuleReference[existingCount + this.targetCount];
+			if (existingCount > 0) {
+				System.arraycopy(this.exportReference.targets, 0, moduleRef1, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0, l = this.targetCount; i < l; ++i) {
+				moduleRef1[actualCount++] = this.targets[i].updatedModuleReference();
+			}
+			this.exportReference.targets = moduleRef1;
+		}
+		return this.exportReference;
+	}
+	public void updateParseTree(){
+		updatedExportReference();
+	}
+	/*
+	 * Update the declarationSourceEnd of the corresponding parse node
+	 */
+	public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+		if (this.exportReference.declarationSourceEnd == 0) {
+			this.exportReference.declarationSourceEnd = bodyEnd;
+			this.exportReference.declarationEnd = bodyEnd;
+		}
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java
new file mode 100644
index 0000000..b636946
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredExportsStatement.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+
+public class RecoveredExportsStatement extends RecoveredPackageVisibilityStatement {
+
+	public RecoveredExportsStatement(ExportsStatement exportsStatement, RecoveredElement parent, int bracketBalance) {
+		super(exportsStatement, parent, bracketBalance);
+	}
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered exports stmt: " + super.toString(); //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java
new file mode 100644
index 0000000..0fa471a
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModule.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleStatement;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
+
+public class RecoveredModule extends RecoveredElement {
+	
+	public RecoveredExportsStatement[] exports;
+	public int exportCount;
+	public RecoveredOpensStatement[] opens;
+	public int opensCount;
+	public RecoveredRequiresStatement[] requires;
+	public int requiresCount;
+	public RecoveredUsesStatement[] uses;
+	public int usesCount;
+	public RecoveredProvidesStatement[] services;
+	public int servicesCount;
+	public ModuleDeclaration moduleDeclaration;
+
+	public RecoveredModule(ModuleDeclaration moduleDeclaration, RecoveredElement parent, int bracketBalance) {
+		super(parent, bracketBalance);
+		this.moduleDeclaration = moduleDeclaration;
+	}
+	public RecoveredElement add(ModuleStatement moduleStatement, int bracketBalanceValue) {
+		
+		// TODO: can't we do away with all these additions except for ProvidesStatement - to check
+		// if there are any corner cases that uses these.
+		if (moduleStatement instanceof ExportsStatement) {
+			return add((ExportsStatement) moduleStatement, bracketBalanceValue);
+		}
+		if (moduleStatement instanceof OpensStatement) {
+			return add((OpensStatement) moduleStatement, bracketBalanceValue);
+		}
+		if (moduleStatement instanceof RequiresStatement) {
+			return add((RequiresStatement) moduleStatement, bracketBalanceValue);
+		}
+		if (moduleStatement instanceof ProvidesStatement) {
+			return add((ProvidesStatement) moduleStatement, bracketBalanceValue);
+		}
+		if (moduleStatement instanceof UsesStatement) {
+			return add((UsesStatement) moduleStatement, bracketBalanceValue);
+		}
+		
+		return this;
+	}
+
+	public RecoveredElement add(ExportsStatement exportsStatement, int bracketBalanceValue) {
+		resetPendingModifiers();
+
+		if (this.exports == null) {
+			this.exports = new RecoveredExportsStatement[5];
+			this.exportCount = 0;
+		} else {
+			if (this.exportCount == this.exports.length) {
+				System.arraycopy(
+					this.exports,
+					0,
+					(this.exports = new RecoveredExportsStatement[2 * this.exportCount]),
+					0,
+					this.exportCount);
+			}
+		}
+		RecoveredExportsStatement element = new RecoveredExportsStatement(exportsStatement, this, bracketBalanceValue);
+		this.exports[this.exportCount++] = element;
+
+		return element;
+	}
+	public RecoveredElement add(OpensStatement opensStatement, int bracketBalanceValue) {
+		resetPendingModifiers();
+
+		if (this.opens == null) {
+			this.opens = new RecoveredOpensStatement[5];
+			this.opensCount = 0;
+		} else {
+			if (this.opensCount == this.opens.length) {
+				System.arraycopy(
+					this.opens,
+					0,
+					(this.opens = new RecoveredOpensStatement[2 * this.opensCount]),
+					0,
+					this.opensCount);
+			}
+		}
+		RecoveredOpensStatement element = new RecoveredOpensStatement(opensStatement, this, bracketBalanceValue);
+		this.opens[this.opensCount++] = element;
+
+		return element;
+	}
+	public RecoveredElement add(RequiresStatement requiresStatement, int bracketBalanceValue) {
+		if (this.requires == null) {
+			this.requires = new RecoveredRequiresStatement[5];
+			this.requiresCount = 0;
+		} else {
+			if (this.requiresCount == this.requires.length) {
+				System.arraycopy(
+					this.requires,
+					0,
+					(this.requires = new RecoveredRequiresStatement[2 * this.requiresCount]),
+					0,
+					this.requiresCount);
+			}
+		}
+		RecoveredRequiresStatement element = new RecoveredRequiresStatement(requiresStatement, this, bracketBalanceValue);
+		this.requires[this.requiresCount++] = element;
+		return this;
+	}
+	public RecoveredElement add(ProvidesStatement providesStatement, int bracketBalanceValue) {
+		if (this.services == null) {
+			this.services = new RecoveredProvidesStatement[5];
+			this.servicesCount = 0;
+		} else {
+			if (this.servicesCount == this.services.length) {
+				System.arraycopy(
+					this.services,
+					0,
+					(this.services = new RecoveredProvidesStatement[2 * this.servicesCount]),
+					0,
+					this.servicesCount);
+			}
+		}
+		RecoveredProvidesStatement element = new RecoveredProvidesStatement(providesStatement, this, bracketBalanceValue);
+		this.services[this.servicesCount++] = element;
+		return element;
+	}
+	public RecoveredElement add(UsesStatement usesStatement, int bracketBalanceValue) {
+		genAssign(usesStatement, bracketBalanceValue);
+		return this;
+	}
+	private void genAssign(UsesStatement usesStatement, int bracketBalanceValue) {
+		if (this.uses == null) {
+			this.uses = new RecoveredUsesStatement[5];
+			this.usesCount = 0;
+		} else {
+			if (this.usesCount == this.uses.length) {
+				System.arraycopy(
+					this.uses,
+					0,
+					(this.uses = new RecoveredUsesStatement[2 * this.usesCount]),
+					0,
+					this.usesCount);
+			}
+		}
+		RecoveredUsesStatement element = new RecoveredUsesStatement(usesStatement, this, bracketBalanceValue);
+		this.uses[this.usesCount++] = element;
+	}
+	public String toString(int tab) {
+		StringBuffer result = new StringBuffer(tabString(tab));
+		result.append("Recovered module:\n"); //$NON-NLS-1$
+		result.append("module ");//$NON-NLS-1$
+		result.append(CharOperation.charToString(this.moduleDeclaration.moduleName));
+		result.append(" {");//$NON-NLS-1$
+		if (this.exportCount > 0) {
+			for (int i = 0; i < this.exportCount; ++i) {
+				result.append("\n"); //$NON-NLS-1$
+				result.append(this.exports[i].toString(tab + 1));
+			}
+		}
+		if (this.requiresCount > 0) {
+			for (int i = 0; i < this.requiresCount; ++i) {
+				result.append("\n"); //$NON-NLS-1$
+				result.append(this.requires[i].toString(tab + 1));
+			}
+		}
+		if (this.usesCount > 0) {
+			for (int i = 0; i < this.usesCount; ++i) {
+				result.append("\n"); //$NON-NLS-1$
+				result.append(this.uses[i].toString(tab + 1));
+			}
+		}
+		if (this.servicesCount > 0) {
+			for (int i = 0; i < this.servicesCount; ++i) {
+				result.append("\n"); //$NON-NLS-1$
+				result.append(this.services[i].toString(tab + 1));
+			}
+		}
+		result.append("\n}");//$NON-NLS-1$
+		return result.toString();
+	}
+	public ModuleDeclaration updatedModuleDeclaration() {
+
+		updateExports(this.moduleDeclaration);
+		updateOpens(this.moduleDeclaration);
+		updateRequires(this.moduleDeclaration);
+		updateUses(this.moduleDeclaration);
+		updateServices(this.moduleDeclaration);
+		return this.moduleDeclaration;
+	}
+	private void updateExports(ModuleDeclaration mod) {
+		if (this.exportCount > 0) {
+			int existingCount = mod.exportsCount, actualCount = 0;
+			ExportsStatement[] exports1 = new ExportsStatement[existingCount + this.exportCount];
+			if (existingCount > 0){
+				System.arraycopy(mod.exports, 0, exports1, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0; i < this.exportCount; i++){
+				exports1[actualCount++] = (ExportsStatement)this.exports[i].updatedPackageVisibilityStatement();
+			}
+			mod.exports = exports1;
+			mod.exportsCount = actualCount;
+		}
+	}
+	private void updateOpens(ModuleDeclaration mod) {
+		if (this.opensCount > 0) {
+			int existingCount = mod.opensCount, actualCount = 0;
+			OpensStatement[] opens1 = new OpensStatement[existingCount + this.opensCount];
+			if (existingCount > 0){
+				System.arraycopy(mod.exports, 0, opens1, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0; i < this.opensCount; i++){
+				opens1[actualCount++] = (OpensStatement)this.opens[i].updatedPackageVisibilityStatement();
+			}
+			mod.opens = opens1;
+			mod.opensCount = actualCount;
+		}
+	}
+	private void updateRequires(ModuleDeclaration mod) {
+		if (this.requiresCount > 0) {
+			int existingCount = mod.requiresCount, actualCount = 0;
+			RequiresStatement[] requiresStmts = new RequiresStatement[existingCount + this.requiresCount];
+			if (existingCount > 0){
+				System.arraycopy(mod.requires, 0, requiresStmts, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0; i < this.requiresCount; i++){
+				requiresStmts[actualCount++] = this.requires[i].updatedRequiresStatement();
+			}
+			mod.requires = requiresStmts;
+			mod.requiresCount = actualCount;
+		}
+	}
+	private void updateUses(ModuleDeclaration mod) {
+		if (this.usesCount > 0) {
+			int existingCount = mod.usesCount, actualCount = 0;
+			UsesStatement[] usesStmts = new UsesStatement[existingCount + this.usesCount];
+			if (existingCount > 0){
+				System.arraycopy(mod.uses, 0, usesStmts, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0; i < this.usesCount; ++i) {
+				usesStmts[actualCount++] = this.uses[i].updatedUsesStatement();
+			}
+			mod.uses = usesStmts;
+			mod.usesCount = actualCount;
+		}
+	}
+	private void updateServices(ModuleDeclaration mod) {
+		if (this.servicesCount > 0) {
+			int existingCount = mod.servicesCount, actualCount = 0;
+			ProvidesStatement[] providesStmts = new ProvidesStatement[existingCount + this.servicesCount];
+			if (existingCount > 0){
+				System.arraycopy(mod.services, 0, providesStmts, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0; i < this.servicesCount; ++i) {
+				providesStmts[actualCount++] = this.services[i].updatedProvidesStatement();
+			}
+			mod.services = providesStmts;
+			mod.servicesCount = actualCount;  			
+		}
+	}
+	public void updateParseTree(){
+		updatedModuleDeclaration();
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java
new file mode 100644
index 0000000..16aa401
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleReference.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+
+public class RecoveredModuleReference extends RecoveredElement {
+
+	public ModuleReference moduleReference;
+public RecoveredModuleReference(ModuleReference moduleReference, RecoveredElement parent, int bracketBalance){
+	super(parent, bracketBalance);
+	this.moduleReference = moduleReference;
+}
+/*
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+	return this.moduleReference;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+	return this.moduleReference.sourceEnd;
+}
+public String toString(int tab) {
+	return tabString(tab) + "Recovered ModuleReference: " + this.moduleReference.toString(); //$NON-NLS-1$
+}
+public ModuleReference updatedModuleReference(){
+
+	return this.moduleReference;
+}
+public void updateParseTree(){
+	updatedModuleReference();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+//public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+//	if (this.moduleReference.declarationSourceEnd == 0) {
+//		this.moduleReference.declarationSourceEnd = bodyEnd;
+//		this.moduleReference.declarationEnd = bodyEnd;
+//	}
+//}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java
new file mode 100644
index 0000000..ff207f6
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredModuleStatement.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ModuleStatement;
+
+public abstract class RecoveredModuleStatement extends RecoveredElement {
+
+	public ModuleStatement moduleStatement;
+
+	public RecoveredModuleStatement(ModuleStatement moduleStmt, RecoveredElement parent, int bracketBalance) {
+		super(parent, bracketBalance);
+		this.moduleStatement = moduleStmt;
+	}
+	/*
+	 * Answer the associated parsed structure
+	 */
+	public ASTNode parseTree(){
+		return this.moduleStatement;
+	}
+	/*
+	 * Answer the very source end of the corresponding parse node
+	 */
+	public int sourceEnd(){
+		return this.moduleStatement.declarationSourceEnd;
+	}
+	public String toString(int tab) {
+		return this.moduleStatement.toString();
+	}
+	protected ModuleStatement updatedModuleStatement(){
+		return this.moduleStatement;
+	}
+	public void updateParseTree(){
+		updatedModuleStatement();
+	}
+	/*
+	 * Update the declarationSourceEnd of the corresponding parse node
+	 */
+	public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+		if (this.moduleStatement.declarationSourceEnd == 0) {
+			this.moduleStatement.declarationSourceEnd = bodyEnd;
+			this.moduleStatement.declarationEnd = bodyEnd;
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java
new file mode 100644
index 0000000..1e97c71
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredOpensStatement.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
+
+public class RecoveredOpensStatement extends RecoveredPackageVisibilityStatement {
+
+	public RecoveredOpensStatement(OpensStatement opensStatement, RecoveredElement parent, int bracketBalance) {
+		super(opensStatement, parent, bracketBalance);
+	}
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered opens stmt: " + super.toString(); //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java
new file mode 100644
index 0000000..fe4c7ac
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredPackageVisibilityStatement.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
+
+public class RecoveredPackageVisibilityStatement extends RecoveredModuleStatement {
+
+	// PackageVisibilityStatement pvs;
+	RecoveredImport pkgRef;
+	RecoveredModuleReference[] targets;
+	int targetCount = 0;
+
+	public RecoveredPackageVisibilityStatement(PackageVisibilityStatement pvs, RecoveredElement parent, int bracketBalance) {
+		super(pvs, parent, bracketBalance);
+	}
+	public RecoveredElement add(ImportReference pkgRef1,  int bracketBalance1) {
+		this.pkgRef = new RecoveredImport(pkgRef1, this, bracketBalance1);
+		return this;
+	}
+	public RecoveredElement add(ModuleReference target,  int bracketBalance1) {
+		if (this.targets == null) {
+			this.targets = new RecoveredModuleReference[5];
+			this.targetCount = 0;
+		} else {
+			if (this.targetCount == this.targets.length) {
+				System.arraycopy(
+					this.targets,
+					0,
+					(this.targets = new RecoveredModuleReference[2 * this.targetCount]),
+					0,
+					this.targetCount);
+			}
+		}
+		RecoveredModuleReference element = new RecoveredModuleReference(target, this, bracketBalance1);
+		this.targets[this.targetCount++] = element;
+		return this;
+
+	}
+	public String toString(int tab) {
+		return super.toString();
+	}
+	public PackageVisibilityStatement updatedPackageVisibilityStatement(){
+		PackageVisibilityStatement pvs = (PackageVisibilityStatement) this.moduleStatement;
+		if (this.pkgRef != null) {
+			pvs.pkgRef = this.pkgRef.updatedImportReference();
+		}
+		if (this.targetCount > 0) {
+			int existingCount = pvs.targets != null ? pvs.targets.length : 0, actualCount = 0;
+			ModuleReference[] moduleRef1 = new ModuleReference[existingCount + this.targetCount];
+			if (existingCount > 0) {
+				System.arraycopy(pvs.targets, 0, moduleRef1, 0, existingCount);
+				actualCount = existingCount;
+			}
+			for (int i = 0, l = this.targetCount; i < l; ++i) {
+				moduleRef1[actualCount++] = this.targets[i].updatedModuleReference();
+			}
+			pvs.targets = moduleRef1;
+		}
+		return pvs;
+	}
+	public void updateParseTree(){
+		updatedPackageVisibilityStatement();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java
new file mode 100644
index 0000000..fb76460
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredProvidesStatement.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+
+public class RecoveredProvidesStatement extends RecoveredModuleStatement {
+	SingleTypeReference impl;
+
+	public RecoveredProvidesStatement(ProvidesStatement providesStatement, RecoveredElement parent, int bracketBalance) {
+		super(providesStatement, parent, bracketBalance);
+	}
+	public RecoveredElement add(SingleTypeReference impl1,  int bracketBalance1) {
+		this.impl = impl1;
+		return this;
+	}
+
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered Provides: " + super.toString(); //$NON-NLS-1$
+	}
+	public ProvidesStatement updatedProvidesStatement(){
+		ProvidesStatement providesStatement = (ProvidesStatement) this.moduleStatement;
+		if (providesStatement.implementations == null) { // only for with - actual impl by normal parse
+			providesStatement.implementations = this.impl != null ? new TypeReference[] {this.impl} : new TypeReference[0]; // dummy for completion
+		}
+		return providesStatement;
+	}
+	public void updateParseTree(){
+		updatedProvidesStatement();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java
new file mode 100644
index 0000000..d7be7a4
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredRequiresStatement.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
+
+public class RecoveredRequiresStatement extends RecoveredModuleStatement {
+
+	public RecoveredRequiresStatement(RequiresStatement requiresStatement, RecoveredElement parent, int bracketBalance) {
+		super(requiresStatement, parent, bracketBalance);
+	}
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered requires: " + super.toString(); //$NON-NLS-1$
+	}
+	public RequiresStatement updatedRequiresStatement(){
+		return (RequiresStatement)this.moduleStatement;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java
new file mode 100644
index 0000000..b98dcd0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredTypeReference.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+
+public class RecoveredTypeReference extends RecoveredElement {
+	public TypeReference typeReference;
+
+	public RecoveredTypeReference(TypeReference typeReference, RecoveredElement parent, int bracketBalance) {
+		super(parent, bracketBalance);
+		this.typeReference = typeReference;
+	}
+
+	/*
+	 * Answer the associated parsed structure
+	 */
+	public ASTNode parseTree(){
+		return this.typeReference;
+	}
+	public TypeReference updateTypeReference() {
+		return this.typeReference;
+	}
+	/*
+	 * Answer the very source end of the corresponding parse node
+	 */
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered typereference: " + this.typeReference.toString(); //$NON-NLS-1$
+	}
+	public TypeReference updatedImportReference(){
+		return this.typeReference;
+	}
+	public void updateParseTree(){
+		updatedImportReference();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
index 0adf1b9..386fb68 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -20,9 +24,11 @@
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 
 public class RecoveredUnit extends RecoveredElement {
@@ -31,6 +37,7 @@
 
 	public RecoveredImport[] imports;
 	public int importCount;
+	public RecoveredModule module;
 	public RecoveredType[] types;
 	public int typeCount;
 
@@ -127,6 +134,10 @@
 	}
 	return this; // ignore
 }
+public RecoveredElement add(ExportsStatement exportReference, int bracketBalanceValue) {
+	return this.module != null ? this.module.add(exportReference, bracketBalanceValue) : null;
+}
+
 public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
 	resetPendingModifiers();
 
@@ -150,8 +161,12 @@
 	if (importReference.declarationSourceEnd == 0) return element;
 	return this;
 }
+public RecoveredElement add(ModuleDeclaration moduleDeclaration, int bracketBalanceValue){
+	this.module = new RecoveredModule(moduleDeclaration, this, bracketBalanceValue);
+	return this.module;
+}
 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
-
+	
 	if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){
 		if (this.typeCount > 0) {
 			// add it to the last type
@@ -243,6 +258,11 @@
 		}
 		this.unitDeclaration.imports = importRefences;
 	}
+	if (this.module != null) {
+		this.unitDeclaration.moduleDeclaration = this.module.updatedModuleDeclaration();
+		this.unitDeclaration.types = new TypeDeclaration[1];
+		this.unitDeclaration.createModuleInfoType(this.unitDeclaration.moduleDeclaration);
+	}
 	/* update types */
 	if (this.typeCount > 0){
 		int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java
new file mode 100644
index 0000000..3f03e65
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUsesStatement.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
+
+public class RecoveredUsesStatement extends RecoveredModuleStatement {
+
+	public RecoveredUsesStatement(UsesStatement usesStatement, RecoveredElement parent, int bracketBalance) {
+		super(usesStatement, parent, bracketBalance);
+	}
+	public String toString(int tab) {
+		return tabString(tab) + "Recovered Uses: " + super.toString(); //$NON-NLS-1$
+	}
+	public UsesStatement updatedUsesStatement(){
+		return (UsesStatement)this.moduleStatement;
+	}
+	public void updateParseTree(){
+		updatedUsesStatement();
+	}
+}
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 771f996..8b46444 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
@@ -98,6 +102,8 @@
 	public int linePtr = -1;
 	public boolean wasAcr = false;
 
+	public boolean fakeInModule = false;
+
 	public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
 
 	public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
@@ -2530,7 +2536,10 @@
 	//newIdentCount++;
 	return table[this.newEntry6 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4, c5});
 }
-
+public boolean isInModuleDeclaration() {
+	return this.fakeInModule || 
+			(this.activeParser != null ? this.activeParser.isParsingModuleDeclaration() : false);
+}
 private void parseTags() {
 	int position = 0;
 	final int currentStartPosition = this.startPosition;
@@ -3093,7 +3102,7 @@
 				default :
 					return TokenNameIdentifier;
 			}
-		case 'e' : //else extends
+		case 'e' : //else extends exports
 			switch (length) {
 				case 4 :
 					if (data[++index] == 'l') {
@@ -3114,15 +3123,18 @@
 					}
 					return TokenNameIdentifier;
 				case 7 :
-					if ((data[++index] == 'x')
-						&& (data[++index] == 't')
-						&& (data[++index] == 'e')
-						&& (data[++index] == 'n')
-						&& (data[++index] == 'd')
-						&& (data[++index] == 's'))
-						return TokenNameextends;
-					else
-						return TokenNameIdentifier;
+						if ((data[++index] == 'x')) {
+							if ((data[++index] == 't') && (data[++index] == 'e') && (data[++index] == 'n')
+									&& (data[++index] == 'd') && (data[++index] == 's')) {
+								return TokenNameextends;
+							} else if (isInModuleDeclaration()
+									&& (data[index] == 'p') && (data[++index] == 'o') && (data[++index] == 'r')
+									&& (data[++index] == 't') && (data[++index] == 's')) {
+								return TokenNameexports;
+							} else
+								return TokenNameIdentifier;
+						} else
+							return TokenNameIdentifier;
 				default :
 					return TokenNameIdentifier;
 			}
@@ -3256,6 +3268,22 @@
 			}
 			return TokenNameIdentifier;
 
+		case 'm': //module
+			switch (length) {
+				case 6 :
+					if (isInModuleDeclaration()
+						&& (data[++index] == 'o')
+						&& (data[++index] == 'd')
+						&& (data[++index] == 'u')
+						&& (data[++index] == 'l')
+						&& (data[++index] == 'e'))
+						return TokenNamemodule;
+					else
+						return TokenNameIdentifier;
+				default :
+					return TokenNameIdentifier;
+			}
+
 		case 'n' : //native new null
 			switch (length) {
 				case 3 :
@@ -3281,7 +3309,26 @@
 					return TokenNameIdentifier;
 			}
 
-		case 'p' : //package private protected public
+		case 'o':
+			switch (length) {
+				case 4 :
+					if (isInModuleDeclaration() && (data[++index] == 'p') && (data[++index] == 'e') && (data[++index] == 'n'))
+						return TokenNameopen;
+					else
+						return TokenNameIdentifier;
+				case 5 :
+					if (isInModuleDeclaration()
+							&& (data[++index] == 'p')
+							&& (data[++index] == 'e')
+							&& (data[++index] == 'n')
+							&& (data[++index] == 's'))
+						return TokenNameopens;
+					else
+						return TokenNameIdentifier;
+				default :
+					return TokenNameIdentifier;
+			}
+		case 'p' : //package private protected public provides
 			switch (length) {
 				case 6 :
 					if ((data[++index] == 'u')
@@ -3312,6 +3359,18 @@
 							return TokenNameprivate;
 						} else
 							return TokenNameIdentifier;
+				case 8 :
+					if (isInModuleDeclaration()
+						&& (data[++index] == 'r')
+						&& (data[++index] == 'o')
+						&& (data[++index] == 'v')
+						&& (data[++index] == 'i')
+						&& (data[++index] == 'd')
+						&& (data[++index] == 'e')
+						&& (data[++index] == 's')) {
+						return TokenNameprovides;
+					} else
+						return TokenNameIdentifier;
 				case 9 :
 					if ((data[++index] == 'r')
 						&& (data[++index] == 'o')
@@ -3329,15 +3388,29 @@
 					return TokenNameIdentifier;
 			}
 
-		case 'r' : //return
-			if (length == 6) {
-				if ((data[++index] == 'e')
-					&& (data[++index] == 't')
-					&& (data[++index] == 'u')
-					&& (data[++index] == 'r')
-					&& (data[++index] == 'n')) {
-					return TokenNamereturn;
-				}
+		case 'r' : //return requires
+			switch (length) {
+				case 6:
+					if ((data[++index] == 'e')
+						&& (data[++index] == 't')
+						&& (data[++index] == 'u')
+						&& (data[++index] == 'r')
+						&& (data[++index] == 'n')) {
+						return TokenNamereturn;
+					} else 
+						return TokenNameIdentifier;
+				case 8:
+					if (isInModuleDeclaration()
+						&& (data[++index] == 'e')
+						&& (data[++index] == 'q')
+						&& (data[++index] == 'u')
+						&& (data[++index] == 'i')
+						&& (data[++index] == 'r')
+						&& (data[++index] == 'e')
+						&& (data[++index] == 's')) {
+						return TokenNamerequires;
+					} else 
+						return TokenNameIdentifier;
 			}
 			return TokenNameIdentifier;
 
@@ -3408,6 +3481,11 @@
 
 		case 't' : //try throw throws transient this true
 			switch (length) {
+				case 2:
+					if (isInModuleDeclaration() && data[++index] == 'o')
+						return TokenNameto;
+					else
+						return TokenNameIdentifier;
 				case 3 :
 					if ((data[++index] == 'r') && (data[++index] == 'y'))
 						return TokenNametry;
@@ -3453,11 +3531,33 @@
 						return TokenNametransient;
 					} else
 						return TokenNameIdentifier;
-
+				case 10:
+					if (isInModuleDeclaration() && (data[++index] == 'r')
+						&& (data[++index] == 'a')
+						&& (data[++index] == 'n')
+						&& (data[++index] == 's')
+						&& (data[++index] == 'i')
+						&& (data[++index] == 't')
+						&& (data[++index] == 'i')
+						&& (data[++index] == 'v')
+						&& (data[++index] == 'e')) {
+						return TokenNametransitive;
+					} else
+						return TokenNameIdentifier;
 				default :
 					return TokenNameIdentifier;
 			}
-
+		case 'u' : //uses
+			switch(length) {
+				case 4 :
+					if (isInModuleDeclaration() 
+							&& (data[++index] == 's') && (data[++index] == 'e') && (data[++index] == 's'))
+						return TokenNameuses;
+					else
+						return TokenNameIdentifier;
+				default :
+					return TokenNameIdentifier;
+			}
 		case 'v' : //void volatile
 			switch (length) {
 				case 4 :
@@ -3481,8 +3581,16 @@
 					return TokenNameIdentifier;
 			}
 
-		case 'w' : //while widefp
+		case 'w' : //while widefp with
 			switch (length) {
+				case 4:
+					if (isInModuleDeclaration()
+						&& (data[++index] == 'i')
+						&& (data[++index] == 't')
+						&& (data[++index] == 'h'))
+						return TokenNamewith;
+					else
+						return TokenNameIdentifier;
 				case 5 :
 					if ((data[++index] == 'h')
 						&& (data[++index] == 'i')
@@ -3996,6 +4104,12 @@
 			return "volatile"; //$NON-NLS-1$
 		case TokenNamewhile :
 			return "while"; //$NON-NLS-1$
+		case TokenNamemodule :
+			return "module"; //$NON-NLS-1$
+		case TokenNamerequires :
+			return "requires"; //$NON-NLS-1$
+		case TokenNameexports :
+			return "exports"; //$NON-NLS-1$
 
 		case TokenNameIntegerLiteral :
 			return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -4212,6 +4326,9 @@
 		case TerminalTokens.TokenNamevoid:
 		case TerminalTokens.TokenNamevolatile:
 		case TerminalTokens.TokenNamewhile:
+		case TerminalTokens.TokenNamemodule:
+		case TerminalTokens.TokenNamerequires:
+		case TerminalTokens.TokenNameexports:
 			return true;
 		default:
 			return false;
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 117cafe..7dd1b06 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * Copyright (c) 2005, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     David Foerster - patch for toUpperCase as described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=153125
@@ -42,6 +46,7 @@
 	private static long[][][] Tables;
 	private static long[][][] Tables7;
 	private static long[][][] Tables8;
+	private static long[][][] Tables9;
 
 	public final static int MAX_OBVIOUS = 128;
 	public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];
@@ -140,6 +145,9 @@
 static void initializeTable18() {
 	Tables8 = initializeTables("unicode6_2"); //$NON-NLS-1$
 }
+static void initializeTable19() {
+	Tables9 = initializeTables("unicode8"); //$NON-NLS-1$
+}
 static long[][][] initializeTables(String unicode_path) {
 	long[][][] tempTable = new long[2][][];
 	tempTable[START_INDEX] = new long[3][];
@@ -286,8 +294,8 @@
 			case 14 :
 				return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF);
 		}
-	} else {
-		// java 7 supports Unicode 6.2
+	} else if (complianceLevel <= ClassFileConstants.JDK1_8) {
+		// java 8 supports Unicode 6.2
 		if (Tables8 == null) {
 			initializeTable18();
 		}
@@ -301,6 +309,21 @@
 			case 14 :
 				return isBitSet(Tables8[PART_INDEX][3], codePoint & 0xFFFF);
 		}
+	} else {
+		// java 9 supports Unicode 8
+		if (Tables9 == null) {
+			initializeTable19();
+		}
+		switch((codePoint & 0x1F0000) >> 16) {
+			case 0 :
+				return isBitSet(Tables9[PART_INDEX][0], codePoint & 0xFFFF);
+			case 1 :
+				return isBitSet(Tables9[PART_INDEX][1], codePoint & 0xFFFF);
+			case 2 :
+				return isBitSet(Tables9[PART_INDEX][2], codePoint & 0xFFFF);
+			case 14 :
+				return isBitSet(Tables9[PART_INDEX][3], codePoint & 0xFFFF);
+		}
 	}
 	return false;
 }
@@ -348,7 +371,7 @@
 			case 2 :
 				return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF);
 		}
-	} else {
+	} else if (complianceLevel <= ClassFileConstants.JDK1_8) {
 		// java 7 supports Unicode 6
 		if (Tables8 == null) {
 			initializeTable18();
@@ -361,6 +384,19 @@
 			case 2 :
 				return isBitSet(Tables8[START_INDEX][2], codePoint & 0xFFFF);
 		}
+	} else {
+		// java 9 supports Unicode 7
+		if (Tables9 == null) {
+			initializeTable19();
+		}
+		switch((codePoint & 0x1F0000) >> 16) {
+			case 0 :
+				return isBitSet(Tables9[START_INDEX][0], codePoint & 0xFFFF);
+			case 1 :
+				return isBitSet(Tables9[START_INDEX][1], codePoint & 0xFFFF);
+			case 2 :
+				return isBitSet(Tables9[START_INDEX][2], codePoint & 0xFFFF);
+		}
 	}
 	return false;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
index 1de9ea0..230d7f4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
@@ -30,127 +30,137 @@
 
 	// special tokens not part of grammar - not autogenerated
 	int TokenNameNotAToken = 0,
-		TokenNameWHITESPACE = 1000,
-		TokenNameCOMMENT_LINE = 1001,
-		TokenNameCOMMENT_BLOCK = 1002,
-		TokenNameCOMMENT_JAVADOC = 1003;
+							TokenNameWHITESPACE = 1000,
+							TokenNameCOMMENT_LINE = 1001,
+							TokenNameCOMMENT_BLOCK = 1002,
+							TokenNameCOMMENT_JAVADOC = 1003;
 
-	int      TokenNameIdentifier = 22,
-      TokenNameabstract = 51,
-      TokenNameassert = 72,
-      TokenNameboolean = 97,
-      TokenNamebreak = 73,
-      TokenNamebyte = 98,
-      TokenNamecase = 99,
-      TokenNamecatch = 100,
-      TokenNamechar = 101,
-      TokenNameclass = 67,
-      TokenNamecontinue = 74,
-      TokenNameconst = 116,
-      TokenNamedefault = 75,
-      TokenNamedo = 76,
-      TokenNamedouble = 102,
-      TokenNameelse = 111,
-      TokenNameenum = 69,
-      TokenNameextends = 96,
-      TokenNamefalse = 38,
-      TokenNamefinal = 52,
-      TokenNamefinally = 109,
-      TokenNamefloat = 103,
-      TokenNamefor = 77,
-      TokenNamegoto = 117,
-      TokenNameif = 78,
-      TokenNameimplements = 114,
-      TokenNameimport = 104,
-      TokenNameinstanceof = 17,
-      TokenNameint = 105,
-      TokenNameinterface = 68,
-      TokenNamelong = 106,
-      TokenNamenative = 53,
-      TokenNamenew = 36,
-      TokenNamenull = 39,
-      TokenNamepackage = 95,
-      TokenNameprivate = 54,
-      TokenNameprotected = 55,
-      TokenNamepublic = 56,
-      TokenNamereturn = 79,
-      TokenNameshort = 107,
-      TokenNamestatic = 40,
-      TokenNamestrictfp = 57,
-      TokenNamesuper = 34,
-      TokenNameswitch = 80,
-      TokenNamesynchronized = 41,
-      TokenNamethis = 35,
-      TokenNamethrow = 81,
-      TokenNamethrows = 112,
-      TokenNametransient = 58,
-      TokenNametrue = 42,
-      TokenNametry = 82,
-      TokenNamevoid = 108,
-      TokenNamevolatile = 59,
-      TokenNamewhile = 71,
-      TokenNameIntegerLiteral = 43,
-      TokenNameLongLiteral = 44,
-      TokenNameFloatingPointLiteral = 45,
-      TokenNameDoubleLiteral = 46,
-      TokenNameCharacterLiteral = 47,
-      TokenNameStringLiteral = 48,
-      TokenNamePLUS_PLUS = 1,
-      TokenNameMINUS_MINUS = 2,
-      TokenNameEQUAL_EQUAL = 19,
-      TokenNameLESS_EQUAL = 12,
-      TokenNameGREATER_EQUAL = 13,
-      TokenNameNOT_EQUAL = 20,
-      TokenNameLEFT_SHIFT = 18,
-      TokenNameRIGHT_SHIFT = 14,
-      TokenNameUNSIGNED_RIGHT_SHIFT = 16,
-      TokenNamePLUS_EQUAL = 84,
-      TokenNameMINUS_EQUAL = 85,
-      TokenNameMULTIPLY_EQUAL = 86,
-      TokenNameDIVIDE_EQUAL = 87,
-      TokenNameAND_EQUAL = 88,
-      TokenNameOR_EQUAL = 89,
-      TokenNameXOR_EQUAL = 90,
-      TokenNameREMAINDER_EQUAL = 91,
-      TokenNameLEFT_SHIFT_EQUAL = 92,
-      TokenNameRIGHT_SHIFT_EQUAL = 93,
-      TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 94,
-      TokenNameOR_OR = 31,
-      TokenNameAND_AND = 30,
-      TokenNamePLUS = 4,
-      TokenNameMINUS = 5,
-      TokenNameNOT = 62,
-      TokenNameREMAINDER = 8,
-      TokenNameXOR = 23,
-      TokenNameAND = 21,
-      TokenNameMULTIPLY = 6,
-      TokenNameOR = 26,
-      TokenNameTWIDDLE = 63,
-      TokenNameDIVIDE = 9,
-      TokenNameGREATER = 15,
-      TokenNameLESS = 11,
-      TokenNameLPAREN = 24,
-      TokenNameRPAREN = 25,
-      TokenNameLBRACE = 49,
-      TokenNameRBRACE = 32,
-      TokenNameLBRACKET = 10,
-      TokenNameRBRACKET = 64,
-      TokenNameSEMICOLON = 28,
-      TokenNameQUESTION = 29,
-      TokenNameCOLON = 61,
-      TokenNameCOMMA = 33,
-      TokenNameDOT = 3,
-      TokenNameEQUAL = 70,
-      TokenNameAT = 37,
-      TokenNameELLIPSIS = 113,
-      TokenNameARROW = 110,
-      TokenNameCOLON_COLON = 7,
-      TokenNameBeginLambda = 50,
-      TokenNameBeginIntersectionCast = 65,
-      TokenNameBeginTypeArguments = 83,
-      TokenNameElidedSemicolonAndRightBrace = 66,
-      TokenNameAT308 = 27,
-      TokenNameAT308DOTDOTDOT = 115,
-      TokenNameEOF = 60,
-      TokenNameERROR = 118;
+	int TokenNameIdentifier = 22,
+							TokenNameabstract = 51,
+							TokenNameassert = 73,
+							TokenNameboolean = 97,
+							TokenNamebreak = 74,
+							TokenNamebyte = 98,
+							TokenNamecase = 99,
+							TokenNamecatch = 100,
+							TokenNamechar = 101,
+							TokenNameclass = 66,
+							TokenNamecontinue = 75,
+							TokenNameconst = 126,
+							TokenNamedefault = 71,
+							TokenNamedo = 76,
+							TokenNamedouble = 102,
+							TokenNameelse = 111,
+							TokenNameenum = 69,
+							TokenNameextends = 85,
+							TokenNamefalse = 39,
+							TokenNamefinal = 52,
+							TokenNamefinally = 109,
+							TokenNamefloat = 103,
+							TokenNamefor = 77,
+							TokenNamegoto = 127,
+							TokenNameif = 78,
+							TokenNameimplements = 122,
+							TokenNameimport = 104,
+							TokenNameinstanceof = 17,
+							TokenNameint = 105,
+							TokenNameinterface = 68,
+							TokenNamelong = 106,
+							TokenNamenative = 53,
+							TokenNamenew = 36,
+							TokenNamenull = 40,
+							TokenNamepackage = 84,
+							TokenNameprivate = 54,
+							TokenNameprotected = 55,
+							TokenNamepublic = 56,
+							TokenNamereturn = 79,
+							TokenNameshort = 107,
+							TokenNamestatic = 38,
+							TokenNamestrictfp = 57,
+							TokenNamesuper = 34,
+							TokenNameswitch = 80,
+							TokenNamesynchronized = 50,
+							TokenNamethis = 35,
+							TokenNamethrow = 81,
+							TokenNamethrows = 119,
+							TokenNametransient = 58,
+							TokenNametrue = 41,
+							TokenNametry = 82,
+							TokenNamevoid = 108,
+							TokenNamevolatile = 59,
+							TokenNamewhile = 72,
+							TokenNamemodule = 112,
+							TokenNameopen = 113,
+							TokenNamerequires = 114,
+							TokenNametransitive = 120,
+							TokenNameexports = 115,
+							TokenNameopens = 116,
+							TokenNameto = 123,
+							TokenNameuses = 117,
+							TokenNameprovides = 118,
+							TokenNamewith = 124,
+							TokenNameIntegerLiteral = 42,
+							TokenNameLongLiteral = 43,
+							TokenNameFloatingPointLiteral = 44,
+							TokenNameDoubleLiteral = 45,
+							TokenNameCharacterLiteral = 46,
+							TokenNameStringLiteral = 47,
+							TokenNamePLUS_PLUS = 2,
+							TokenNameMINUS_MINUS = 3,
+							TokenNameEQUAL_EQUAL = 19,
+							TokenNameLESS_EQUAL = 12,
+							TokenNameGREATER_EQUAL = 13,
+							TokenNameNOT_EQUAL = 20,
+							TokenNameLEFT_SHIFT = 18,
+							TokenNameRIGHT_SHIFT = 14,
+							TokenNameUNSIGNED_RIGHT_SHIFT = 16,
+							TokenNamePLUS_EQUAL = 86,
+							TokenNameMINUS_EQUAL = 87,
+							TokenNameMULTIPLY_EQUAL = 88,
+							TokenNameDIVIDE_EQUAL = 89,
+							TokenNameAND_EQUAL = 90,
+							TokenNameOR_EQUAL = 91,
+							TokenNameXOR_EQUAL = 92,
+							TokenNameREMAINDER_EQUAL = 93,
+							TokenNameLEFT_SHIFT_EQUAL = 94,
+							TokenNameRIGHT_SHIFT_EQUAL = 95,
+							TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 96,
+							TokenNameOR_OR = 31,
+							TokenNameAND_AND = 30,
+							TokenNamePLUS = 4,
+							TokenNameMINUS = 5,
+							TokenNameNOT = 62,
+							TokenNameREMAINDER = 9,
+							TokenNameXOR = 23,
+							TokenNameAND = 21,
+							TokenNameMULTIPLY = 8,
+							TokenNameOR = 27,
+							TokenNameTWIDDLE = 63,
+							TokenNameDIVIDE = 10,
+							TokenNameGREATER = 15,
+							TokenNameLESS = 11,
+							TokenNameLPAREN = 24,
+							TokenNameRPAREN = 25,
+							TokenNameLBRACE = 48,
+							TokenNameRBRACE = 33,
+							TokenNameLBRACKET = 6,
+							TokenNameRBRACKET = 64,
+							TokenNameSEMICOLON = 26,
+							TokenNameQUESTION = 29,
+							TokenNameCOLON = 61,
+							TokenNameCOMMA = 32,
+							TokenNameDOT = 1,
+							TokenNameEQUAL = 70,
+							TokenNameAT = 37,
+							TokenNameELLIPSIS = 121,
+							TokenNameARROW = 110,
+							TokenNameCOLON_COLON = 7,
+							TokenNameBeginLambda = 49,
+							TokenNameBeginIntersectionCast = 65,
+							TokenNameBeginTypeArguments = 83,
+							TokenNameElidedSemicolonAndRightBrace = 67,
+							TokenNameAT308 = 28,
+							TokenNameAT308DOTDOTDOT = 125,
+							TokenNameEOF = 60,
+							TokenNameERROR = 128;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
index 358ab95..d624df8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
@@ -2557,4 +2557,10 @@
 		*/ 
 		return (token == TokenNameLPAREN || token == TokenNameAT || (token == TokenNameLESS && !this.lexStream.awaitingColonColon()));
 	}
+
+	@Override
+	public boolean isParsingModuleDeclaration() {
+		//
+		return this.parser.isParsingModuleDeclaration();
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index 4c2379e..274fa50 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
index 2baa5b0..867a099 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
index aac797f..2c1fbd3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
index fef4615..07b4bf6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
index e54bfa2..56d678f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
index 960d871..9e8f596 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
index a8b4515..353090b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
index 2d3072a..266bf1b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
index 1edaa27..df3f4df 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
index 34c1880..3a3cedb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
index 0802e32..8bdb123 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
index 53298f4..3031ff9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc
index bdedb09..518ee2a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser22.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc
index 4f2c8cd..c8dd03c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser23.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc
index c68a5c5..ec7d7e6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser24.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
index 1a28e79..9500898 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
index d43992f..a1145dc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
index 0fb6df5..f56c662 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
index 44ce172..28c6b22 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
index a9d2488..30e76fa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
index 17dbb14..e594f6b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
index 3a2935f..4b69399 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part0.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part0.rsc
new file mode 100644
index 0000000..b3d548c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part0.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc
new file mode 100644
index 0000000..0a96c07
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part14.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part14.rsc
new file mode 100644
index 0000000..c8241e8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part14.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part2.rsc
new file mode 100644
index 0000000..f89f581
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/part2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start0.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start0.rsc
new file mode 100644
index 0000000..219835e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start0.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start1.rsc
new file mode 100644
index 0000000..dbfb455
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc
new file mode 100644
index 0000000..f89f581
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode7/start2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc
new file mode 100644
index 0000000..6b106b0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part0.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part1.rsc
new file mode 100644
index 0000000..b472657
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part14.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part14.rsc
new file mode 100644
index 0000000..c8241e8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part14.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part2.rsc
new file mode 100644
index 0000000..d88c8d4
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/part2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc
new file mode 100644
index 0000000..7b6ff8e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start0.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc
new file mode 100644
index 0000000..7ad1dc8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc
new file mode 100644
index 0000000..d88c8d4
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/unicode8/start2.rsc
Binary files differ
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 4046259..be15f50 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Benjamin Muskalla - Contribution for bug 239066
@@ -128,9 +132,13 @@
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
 import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
 import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
+import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
 import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
@@ -166,6 +174,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 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.ParameterizedGenericMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
@@ -196,7 +205,7 @@
 
 	public ReferenceContext referenceContext;
 	private Scanner positionScanner;
-	private boolean underScoreIsLambdaParameter;
+	private boolean underScoreIsError;
 	private final static byte
 	  // TYPE_ACCESS = 0x0,
 	  FIELD_ACCESS = 0x4,
@@ -1338,7 +1347,7 @@
 		nodeSourceStart(local, location),
 		nodeSourceEnd(local, location));
 }
-public void cannotReferToNonEffectivelyFinalOuterLocal(LocalVariableBinding local, ASTNode location) {
+public void cannotReferToNonEffectivelyFinalOuterLocal(VariableBinding local, ASTNode location) {
 	String[] arguments = new String[] { new String(local.readableName()) };
 	this.handle(
 		IProblem.OuterLocalMustBeEffectivelyFinal, 
@@ -1347,6 +1356,15 @@
 		nodeSourceStart(local, location),
 		nodeSourceEnd(local, location));
 }
+public void cannotReferToNonFinalField(VariableBinding local, ASTNode location) {
+	String[] arguments = new String[] { new String(local.readableName()) };
+	this.handle(
+		IProblem.FieldMustBeFinal, 
+		arguments,
+		arguments,
+		nodeSourceStart(local, location),
+		nodeSourceEnd(local, location));
+}
 public void cannotReturnInInitializer(ASTNode location) {
 	this.handle(
 		IProblem.CannotReturnInInitializer,
@@ -1600,7 +1618,7 @@
 		case IProblem.ToleratedMisplacedTypeAnnotations:	
 			return ProblemSeverities.Warning;
 		case IProblem.IllegalUseOfUnderscoreAsAnIdentifier:
-			return this.underScoreIsLambdaParameter ? ProblemSeverities.Error : ProblemSeverities.Warning;
+			return this.underScoreIsError ? ProblemSeverities.Error : ProblemSeverities.Warning;
 		case IProblem.ProblemNotAnalysed:
 			return ProblemSeverities.Info; // Not configurable
 	}
@@ -2695,6 +2713,15 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
+public void illegalModifierCombinationForPrivateInterfaceMethod(AbstractMethodDeclaration methodDecl) {
+	String[] arguments = new String[] {new String(methodDecl.selector)};
+	this.handle(
+		IProblem.IllegalModifierCombinationForPrivateInterfaceMethod9,
+		arguments,
+		arguments,
+		methodDecl.sourceStart,
+		methodDecl.sourceEnd);
+}
 
 public void illegalModifierForAnnotationField(FieldDeclaration fieldDecl) {
 	String name = new String(fieldDecl.name);
@@ -2752,6 +2779,15 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
+public void illegalModifierForModule(ModuleDeclaration module) {
+	String[] arguments = new String[] {new String(module.moduleName)};
+	this.handle(
+		IProblem.IllegalModifierForModule,
+		arguments,
+		arguments,
+		module.sourceStart(),
+		module.sourceEnd());
+}
 public void illegalModifierForEnum(SourceTypeBinding type) {
 	String[] arguments = new String[] {new String(type.sourceName())};
 	this.handle(
@@ -2813,13 +2849,14 @@
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
-public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl, boolean isJDK18orGreater) {
+public void illegalModifierForInterfaceMethod(AbstractMethodDeclaration methodDecl, long  level) {
+	
+	int problem = level < ClassFileConstants.JDK1_8 ? IProblem.IllegalModifierForInterfaceMethod :
+		level < ClassFileConstants.JDK9 ? IProblem.IllegalModifierForInterfaceMethod18 : IProblem.IllegalModifierForInterfaceMethod9;
 	// cannot include parameter types since they are not resolved yet
 	// and the error message would be too long
 	this.handle(
-		isJDK18orGreater 
-			? IProblem.IllegalModifierForInterfaceMethod18 
-			: IProblem.IllegalModifierForInterfaceMethod,
+		problem,
 		new String[] {
 			new String(methodDecl.selector)
 		},
@@ -7451,7 +7488,7 @@
 public void reset() {
 	this.positionScanner = null;
 }
-public void resourceHasToImplementAutoCloseable(TypeBinding binding, TypeReference typeReference) {
+public void resourceHasToImplementAutoCloseable(TypeBinding binding, ASTNode reference) {
 	if (this.options.sourceLevel < ClassFileConstants.JDK1_7) {
 		return; // Not supported in 1.7 would have been reported. Hence another not required
 	}
@@ -7459,8 +7496,8 @@
 			IProblem.ResourceHasToImplementAutoCloseable,
 			new String[] {new String(binding.readableName())},
 			new String[] {new String(binding.shortReadableName())},
-			typeReference.sourceStart,
-			typeReference.sourceEnd);
+			reference.sourceStart,
+			reference.sourceEnd);
 }
 private int retrieveClosingAngleBracketPosition(int start) {
 	if (this.referenceContext == null) return start;
@@ -8213,16 +8250,23 @@
 		sourceEnd);
 }
 public void unhandledExceptionFromAutoClose (TypeBinding exceptionType, ASTNode location) {
-	LocalVariableBinding localBinding = ((LocalDeclaration)location).binding;
-	if (localBinding != null) {
+	Binding binding = null;
+	if (location instanceof LocalDeclaration) {
+		binding = ((LocalDeclaration)location).binding;
+	} else if (location instanceof  NameReference) {
+		binding = ((NameReference) location).binding;
+	} else if (location instanceof FieldReference) {
+		binding = ((FieldReference) location).binding;
+	}
+	if (binding != null) {
 		this.handle(
 			IProblem.UnhandledExceptionOnAutoClose,
 			new String[] {
 					new String(exceptionType.readableName()),
-					new String(localBinding.readableName())},
+					new String(binding.readableName())},
 			new String[] {
 					new String(exceptionType.shortReadableName()),
-					new String(localBinding.shortReadableName())},
+					new String(binding.shortReadableName())},
 			location.sourceStart,
 			location.sourceEnd);
 	}
@@ -9004,8 +9048,8 @@
 		sourceStart,
 		sourceEnd);
 }
-public void illegalUseOfUnderscoreAsAnIdentifier(int sourceStart, int sourceEnd, boolean lambdaParameter) {
-	this.underScoreIsLambdaParameter = lambdaParameter;
+public void illegalUseOfUnderscoreAsAnIdentifier(int sourceStart, int sourceEnd, boolean reportError) {
+	this.underScoreIsError = reportError;
 	try {
 		this.handle(
 			IProblem.IllegalUseOfUnderscoreAsAnIdentifier,
@@ -9014,7 +9058,7 @@
 			sourceStart,
 			sourceEnd);
 	} finally {
-		this.underScoreIsLambdaParameter = false;	
+		this.underScoreIsError = false;	
 	}
 }
 public void varargsArgumentNeedCast(MethodBinding method, TypeBinding argumentType, InvocationSite location) {
@@ -9238,13 +9282,25 @@
 		typeRef.sourceEnd);
 }
 
-public void autoManagedResourcesNotBelow17(LocalDeclaration[] resources) {
+public void autoManagedResourcesNotBelow17(Statement[] resources) {
+	Statement stmt0 = resources[0];
+	Statement stmtn = resources[resources.length - 1];
+	int sourceStart = stmt0 instanceof LocalDeclaration ? ((LocalDeclaration) stmt0).declarationSourceStart : stmt0.sourceStart;
+	int sourceEnd = stmtn instanceof LocalDeclaration ? ((LocalDeclaration) stmtn).declarationSourceEnd : stmtn.sourceEnd;
 	this.handle(
 			IProblem.AutoManagedResourceNotBelow17,
 			NoArgument,
 			NoArgument,
-			resources[0].declarationSourceStart,
-			resources[resources.length - 1].declarationSourceEnd);
+			sourceStart,
+			sourceEnd);
+}
+public void autoManagedVariableResourcesNotBelow9(Expression resource) {
+	this.handle(
+			IProblem.AutoManagedVariableResourceNotBelow9,
+			NoArgument,
+			NoArgument,
+			resource.sourceStart,
+			resource.sourceEnd);
 }
 public void cannotInferElidedTypes(AllocationExpression allocationExpression) {
 	String arguments [] = new String [] { allocationExpression.type.toString() };
@@ -9279,6 +9335,14 @@
 			type.sourceStart, 
 			type.sourceEnd);
 }
+public void anonymousDiamondWithNonDenotableTypeArguments(TypeReference type, TypeBinding tb) {
+	this.handle(
+			IProblem.NonDenotableTypeArgumentForAnonymousDiamond,
+			new String[]{new String(tb.leafComponentType().shortReadableName()), type.toString()},
+			new String[]{new String(tb.leafComponentType().shortReadableName()), type.toString()},
+			type.sourceStart, 
+			type.sourceEnd);
+}
 public void redundantSpecificationOfTypeArguments(ASTNode location, TypeBinding[] argumentTypes) {
 	int severity = computeSeverity(IProblem.RedundantSpecificationOfTypeArguments);
 	if (severity != ProblemSeverities.Ignore) {
@@ -10488,6 +10552,53 @@
 			typeReference[0].sourceStart,
 			typeReference[typeReference.length - 1].sourceEnd);
 }
+public void invalidModule(ModuleReference ref) {
+	this.handle(IProblem.UndefinedModule, 
+		NoArgument, new String[] { CharOperation.charToString(ref.moduleName) },
+		ref.sourceStart, ref.sourceEnd);
+}
+public void invalidOpensStatement(OpensStatement statement, ModuleDeclaration module) {
+	this.handle(IProblem.InvalidOpensStatement,
+		NoArgument, new String[] { CharOperation.charToString(module.moduleName) },
+		statement.declarationSourceStart, statement.declarationSourceEnd);
+}
+public void invalidPackageReference(int problem, PackageVisibilityStatement ref) {
+	this.handle(problem, 
+		NoArgument, new String[] { CharOperation.charToString(ref.pkgName) },
+		ref.sourceStart, ref.sourceEnd);
+}
+
+public void duplicateModuleReference(int problem, ModuleReference ref) {
+	this.handle(problem, 
+		NoArgument, new String[] { CharOperation.charToString(ref.moduleName) },
+		ref.sourceStart, ref.sourceEnd);
+}
+public void duplicateTypeReference(int problem, TypeReference ref) {
+	this.handle(problem, 
+		NoArgument, new String[] { ref.toString() },
+		ref.sourceStart, ref.sourceEnd);
+}
+public void duplicateTypeReference(int problem, TypeReference ref1, TypeReference ref2) {
+	this.handle(problem, 
+		NoArgument, new String[] { ref1.toString(), ref2.toString() },
+		ref1.sourceStart, ref2.sourceEnd);
+}
+public void duplicateResourceReference(Reference ref) {
+	this.handle(IProblem.DuplicateResource, 
+		NoArgument, new String[] {ref.toString() },
+		ProblemSeverities.Warning,
+		ref.sourceStart, ref.sourceEnd);
+}
+public void cyclicModuleDependency(ModuleBinding binding, ModuleReference ref) {
+	this.handle(IProblem.CyclicModuleDependency, 
+		NoArgument, new String[] { CharOperation.charToString(binding.moduleName), CharOperation.charToString(ref.moduleName) },
+		ref.sourceStart, ref.sourceEnd);
+}
+public void invalidServiceRef(int problem, TypeReference type) {
+	this.handle(problem,
+		NoArgument, new String[] { CharOperation.charToString(type.resolvedType.readableName()) },
+		type.sourceStart, type.sourceEnd);
+}
 
 public void unlikelyArgumentType(Expression argument, MethodBinding method, TypeBinding argumentType,
 							TypeBinding receiverType, DangerousMethod dangerousMethod)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 9467acc..345fcf6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -5,6 +5,9 @@
 # which accompanies this distribution, and is available at
 # http://www.eclipse.org/legal/epl-v10.html
 #
+# This is an implementation of an early-draft specification developed under the Java
+# Community Process (JCP) and is made available for testing and evaluation purposes
+# only. The code is not compatible with any specification of the JCP.
 #
 # Contributors:
 #     IBM Corporation - initial API and implementation
@@ -666,6 +669,7 @@
 666 = Syntax error, type annotations are illegal here
 667 = Super method references to interface default methods are allowed only at source level 1.8 or above
 668 = References to interface static methods are allowed only at source level 1.8 or above
+669 = Field {0} must be final
 
 ### NULL ANALYSIS FOR OTHER EXPRESSIONS
 670 = Null comparison always yields false: this expression cannot be null
@@ -763,6 +767,9 @@
 #[obsolete] 895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
 896 = Static methods are allowed in interfaces only at source level 1.8 or above
 
+#### Java 9
+876 = Variable resource not allowed here for source level below 9
+
 897 = Duplicate annotation of non-repeatable type @{0}. Only annotation types marked @Repeatable can be used multiple times at one target.
 898 = The annotation @{0} cannot be repeated at this location since its container annotation type @{1} is disallowed at this location
 899 = The repeatable annotation @{0} may not be repeated where its container annotation type @{1} is also used directly
@@ -865,13 +872,41 @@
 1062 = Nullness default is redundant with a default specified for the variable {0}
 1063 = Nullness default is redundant with a default specified for the field {0}
 
+1070 = Illegal combination of modifiers for the private interface method {0}; additionally only one of static and strictfp is permitted
+1071 = Illegal modifier for the interface method {0}; only public, private, abstract, default, static and strictfp are permitted
+
 1100 = Problem detected during type inference: {0}
 #1101 is already used up but deprecated
 1102 = At least one of the problems in category ''{0}'' is not analysed due to a compiler option being ignored
+
 # more programming problems:
 1200 = Unlikely argument type {0} for {1} on a {2}
 1201 = Unlikely argument type for equals(): {0} seems to be unrelated to {2}
 
+### Autoclosable try
+1251 = Duplicate resource reference {0}
+
+# Java9 - Module declaration related
+1300 = {0} cannot be resolved to a module
+1301 = Duplicate requires entry: {0}
+1302 = Duplicate exports entry: {0}
+1303 = Duplicate uses entry: {0}
+1304 = Duplicate service entry: {0}
+1305 = Cycle exists in module dependencies, Module {0} requires itself via {1}
+1306 = Invalid service implementation, the type {0} is abstract
+1307 = The service implementation {0} must define a public static provider method or a no-arg constructor
+1308 = The no-arg constructor of service implementation {0} is not public
+1309 = Invalid service implementation, the type {0} is an inner class
+1310 = Service implementation {0} is not defined in the module with the provides directive
+1311 = The package {0} does not exist or is empty
+1312 = Type {0} inferred for {1}, is not valid for an anonymous class with '<>'
+1313 = Duplicate opens entry: {0}
+1314 = Duplicate module name: {0}
+1315 = opens statement is not allowed, as module {0} is declared open
+1316 = Invalid service interface {0}, must be a class, interface or annotation type
+1317 = Invalid service implementation {0}, must be a public class or interface type
+1318 = Illegal modifier for module {0}; only open is permitted
+
 ### ELABORATIONS
 ## Access restrictions
 78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'')
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java
new file mode 100644
index 0000000..1bd6eb2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfModule.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+
+public final class HashtableOfModule {
+	// to avoid using Enumerations, walk the individual tables skipping nulls
+	public char[] keyTable[];
+	public ModuleBinding valueTable[];
+
+	public int elementSize; // number of elements in the table
+	int threshold;
+	public HashtableOfModule() {
+		this(3); // usually not very large
+	}
+	public HashtableOfModule(int size) {
+		this.elementSize = 0;
+		this.threshold = size; // size represents the expected number of elements
+		int extraRoom = (int) (size * 1.75f);
+		if (this.threshold == extraRoom)
+			extraRoom++;
+		this.keyTable = new char[extraRoom][];
+		this.valueTable = new ModuleBinding[extraRoom];
+	}
+	public boolean containsKey(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 true;
+			if (++index == length) {
+				index = 0;
+			}
+		}
+		return false;
+	}
+	public ModuleBinding 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 (++index == length) {
+				index = 0;
+			}
+		}
+		return null;
+	}
+	public ModuleBinding put(char[] key, ModuleBinding value) {
+		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] = value;
+			if (++index == length) {
+				index = 0;
+			}
+		}
+		this.keyTable[index] = key;
+		this.valueTable[index] = value;
+
+		// assumes the threshold is never equal to the size of the table
+		if (++this.elementSize > this.threshold)
+			rehash();
+		return value;
+	}
+	private void rehash() {
+		HashtableOfModule newHashtable = new HashtableOfModule(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)
+				newHashtable.put(currentKey, this.valueTable[i]);
+
+		this.keyTable = newHashtable.keyTable;
+		this.valueTable = newHashtable.valueTable;
+		this.threshold = newHashtable.threshold;
+	}
+	public int size() {
+		return this.elementSize;
+	}
+	public String toString() {
+		String s = ""; //$NON-NLS-1$
+		ModuleBinding pkg;
+		for (int i = 0, length = this.valueTable.length; i < length; i++)
+			if ((pkg = this.valueTable[i]) != null)
+				s += pkg.toString() + "\n"; //$NON-NLS-1$
+		return s;
+	}
+}
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
new file mode 100644
index 0000000..635ea4e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -0,0 +1,424 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
+
+public class JRTUtil {
+
+	public static final String JAVA_BASE = "java.base"; //$NON-NLS-1$
+	public static final char[] JAVA_BASE_CHAR = JAVA_BASE.toCharArray();
+	static final String MODULES_SUBDIR = "/modules"; //$NON-NLS-1$
+	static final String[] DEFAULT_MODULE = new String[]{JAVA_BASE};
+	static final String[] NO_MODULE = new String[0];
+	static final String MULTIPLE = "MU"; //$NON-NLS-1$
+	static final String DEFAULT_PACKAGE = ""; //$NON-NLS-1$
+	static String MODULE_TO_LOAD = null;
+	public static final String JRT_FS_JAR = "jrt-fs.jar"; //$NON-NLS-1$
+	static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
+	public static int NOTIFY_FILES = 0x0001;
+	public static int NOTIFY_PACKAGES = 0x0002;
+	public static int NOTIFY_MODULES = 0x0004;
+	public static int NOTIFY_ALL = NOTIFY_FILES | NOTIFY_PACKAGES | NOTIFY_MODULES;
+
+	// TODO: BETA_JAVA9 Think about clearing the cache too.
+	private static Map<File, JrtFileSystem> images = null;
+
+	private static final Object lock = new Object();
+
+	public interface JrtFileVisitor<T> {
+
+		public FileVisitResult visitPackage(T dir, T mod, BasicFileAttributes attrs) throws IOException;
+
+		public FileVisitResult visitFile(T file, T mod, BasicFileAttributes attrs) throws IOException;
+		/**
+		 * Invoked when a root directory of a module being visited. The element returned 
+		 * contains only the module name segment - e.g. "java.base". Clients can use this to control
+		 * how the JRT needs to be processed, for e.g., clients can skip a particular module
+		 * by returning FileVisitResult.SKIP_SUBTREE
+		 */
+		public FileVisitResult visitModule(T mod) throws IOException;
+	}
+
+	static abstract class AbstractFileVisitor<T> implements FileVisitor<T> {
+		@Override
+		public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	
+		@Override
+		public FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	
+		@Override
+		public FileVisitResult visitFileFailed(T file, IOException exc) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	
+		@Override
+		public FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	}
+
+	public static JrtFileSystem getJrtSystem(File image) {
+		Map<File, JrtFileSystem> i = images;
+		if (images == null) {
+			synchronized (lock) {
+	            i = images;
+	            if (i == null) {
+	            	images = i = new HashMap<>();
+	            }
+	        }
+		}
+		JrtFileSystem system = null;
+		synchronized(i) {
+			if ((system = images.get(image)) == null) {
+				try {
+					images.put(image, system = new JrtFileSystem(image));
+				} catch (IOException e) {
+					e.printStackTrace();
+					// Needs better error handling downstream? But for now, make sure 
+					// a dummy JrtFileSystem is not created.
+				}
+			}
+		}
+	    return system;
+	}
+
+	/**
+	 * Given the path of a modular image file, this method walks the archive content and
+	 * notifies the supplied visitor about packages and files visited.
+	 *
+	 * The file system contains the following top level directories:
+	 *  /modules/$MODULE/$PATH
+	 *  /packages/$PACKAGE/$MODULE 
+	 *  The latter provides quick look up of the module that contains a particular package. However,
+	 *  this method only notifies its clients of the entries within the modules sub-directory. The
+	 *  clients can decide which notifications they want to receive. See {@link JRTUtil#NOTIFY_ALL},
+	 *  {@link JRTUtil#NOTIFY_FILES}, {@link JRTUtil#NOTIFY_PACKAGES} and {@link JRTUtil#NOTIFY_MODULES}.
+	 *
+	 * @param image a java.io.File handle to the JRT image.
+	 * @param visitor an instance of JrtFileVisitor to be notified of the entries in the JRT image.
+	 * @param notify flag indicating the notifications the client is interested in.
+	 * @throws IOException
+	 */
+	public static void walkModuleImage(File image, final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, int notify) throws IOException {
+		getJrtSystem(image).walkModuleImage(visitor, false, notify);
+	}
+
+	public static InputStream getContentFromJrt(File jrt, String fileName, String module) throws IOException {
+		return getJrtSystem(jrt).getContentFromJrt(fileName, module);
+	}
+	public static byte[] getClassfileContent(File jrt, String fileName, String module) throws IOException, ClassFormatException {
+		return getJrtSystem(jrt).getClassfileContent(fileName, module);
+	}
+	public static ClassFileReader getClassfile(File jrt, String fileName, IModule module) throws IOException, ClassFormatException {
+		return getJrtSystem(jrt).getClassfile(fileName, module);
+	}
+	public static ClassFileReader getClassfile(File jrt, String fileName, Optional<Collection<char[]>> modules) throws IOException, ClassFormatException {
+		return getJrtSystem(jrt).getClassfile(fileName, modules);
+	}
+	public static boolean isPackage(File jrt, String qName, Optional<char[]> module) {
+		return getJrtSystem(jrt).isPackage(qName, module);
+	}
+}
+class JrtFileSystem {
+	private final Map<String, String> packageToModule = new HashMap<String, String>();
+
+	private final Map<String, List<String>> packageToModules = new HashMap<String, List<String>>();
+
+	FileSystem jrtSystem = null;
+	
+	/**
+	 * The jrt file system is based on the location of the JRE home whose libraries
+	 * need to be loaded.
+	 *
+	 * @param jrt the path to the root of the JRE whose libraries we are interested in.
+	 * @throws IOException 
+	 */
+	public JrtFileSystem(File jrt) throws IOException {
+		initialize(jrt);
+	}
+	void initialize(File jrt) throws IOException {
+		URL jrtPath = null;
+		String jdkHome = null;
+		if (jrt.toString().endsWith(JRTUtil.JRT_FS_JAR)) {
+			jrtPath = jrt.toPath().toUri().toURL();
+			jdkHome = jrt.getParentFile().getParent();
+		} else {
+			jdkHome = jrt.toPath().toString();
+			jrtPath = Paths.get(jdkHome, "lib", JRTUtil.JRT_FS_JAR).toUri().toURL(); //$NON-NLS-1$
+
+		}
+		JRTUtil.MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$
+		String javaVersion = System.getProperty("java.version"); //$NON-NLS-1$
+		if (javaVersion != null && javaVersion.startsWith("1.8")) { //$NON-NLS-1$
+			JRTUtil.MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$
+			URLClassLoader loader = new URLClassLoader(new URL[] { jrtPath });
+			HashMap<String, ?> env = new HashMap<>();
+			this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env, loader);
+		} else {
+			HashMap<String, String> env = new HashMap<>();
+			env.put("java.home", jdkHome); //$NON-NLS-1$
+			this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env);
+		}
+		walkModuleImage(null, true, 0 /* doesn't matter */);
+	}
+
+	public boolean isPackage(String qualifiedPackageName, Optional<char[]> moduleName) {
+		qualifiedPackageName = qualifiedPackageName.replace('.', '/');
+		String module = this.packageToModule.get(qualifiedPackageName);
+		if (!moduleName.isPresent())
+			return module != null;
+		if (module != null) {
+			if (module == JRTUtil.MULTIPLE) {
+				List<String> list = this.packageToModules.get(qualifiedPackageName);
+				return list.contains(new String(moduleName.get()));
+			} else {
+				return CharOperation.equals(module.toCharArray(), moduleName.get());
+			}
+		}
+		return false;
+	}
+	public String[] getModules(String fileName) {
+		int idx = fileName.lastIndexOf('/');
+		String pack = null;
+		if (idx != -1) {
+			pack = fileName.substring(0, idx);
+		} else {
+			pack = JRTUtil.DEFAULT_PACKAGE;
+		}
+		String module = this.packageToModule.get(pack);
+		if (module != null) {
+			if (module == JRTUtil.MULTIPLE) {
+				List<String> list = this.packageToModules.get(pack);
+				return list.toArray(new String[list.size()]);
+			} else {
+				return new String[]{module};
+			}
+		}
+		return JRTUtil.DEFAULT_MODULE;
+	}
+
+	public InputStream getContentFromJrt(String fileName, String module) throws IOException {
+		if (module != null) {
+			return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
+		}
+		String[] modules = getModules(fileName);
+		for (String mod : modules) {
+			return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+		}
+		return null;
+	}
+	private ClassFileReader getClassfile(String fileName) throws IOException, ClassFormatException {
+		String[] modules = getModules(fileName);
+		byte[] content = null;
+		String module = null;
+		for (String mod : modules) {
+			try {
+				content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+				if (content != null) {
+					module = mod;
+					break;
+				}
+			} catch(NoSuchFileException e) {
+				continue;
+			}
+		}
+		if (content != null) {
+			return new ClassFileReader(content, fileName.toCharArray(), module.toCharArray());
+		}
+		return null;
+	}
+
+	byte[] getClassfileContent(String fileName, String module) throws IOException, ClassFormatException {
+		byte[] content = null;
+		if (module != null) {
+			content = getClassfile(fileName, new String(module.toCharArray()));
+		} else {
+			String[] modules = getModules(fileName);
+			for (String mod : modules) {
+				try {
+					content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+					if (content != null) {
+						break;
+					}
+				} catch(NoSuchFileException e) {
+					continue;
+				}
+			}
+		}
+		return content;
+	}
+	private byte[] getClassfile(String fileName, String module) throws IOException, ClassFormatException {
+		byte[] content = null;
+		try {
+			content = Files.readAllBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
+		} catch(NoSuchFileException e) {
+			return null;
+		}
+		return content;
+	}
+	public ClassFileReader getClassfile(String fileName, Optional<Collection<char[]>> modules) throws IOException, ClassFormatException {
+		ClassFileReader reader = null;
+		if (!modules.isPresent()) {
+			reader = getClassfile(fileName);
+		} else {
+			Iterator<char[]> modIterator = modules.get().iterator();
+			while(modIterator.hasNext()) {
+				char[] mod = modIterator.next();
+				byte[] content = getClassfile(fileName, new String(mod));
+				if (content != null) {
+					reader = new ClassFileReader(content, fileName.toCharArray(), mod);
+					break;
+				}
+			}
+		}
+		return reader;
+	}
+	public ClassFileReader getClassfile(String fileName, IModule module) throws IOException, ClassFormatException {
+		ClassFileReader reader = null;
+		if (module == null || module == ModuleEnvironment.UNNAMED_MODULE) {
+			reader = getClassfile(fileName);
+		} else {
+			byte[] content = getClassfile(fileName, new String(module.name()));
+			if (content != null) {
+				reader = new ClassFileReader(content, fileName.toCharArray(), module.name());
+			}
+		}
+		return reader;
+	}
+
+	void walkModuleImage(final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, boolean visitPackageMapping, final int notify) throws IOException {
+		Iterable<java.nio.file.Path> roots = this.jrtSystem.getRootDirectories();
+		for (java.nio.file.Path path : roots) {
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
+				for (final java.nio.file.Path subdir: stream) {
+					if (subdir.toString().equals(JRTUtil.MODULES_SUBDIR)) {
+						if (visitPackageMapping) continue;
+						Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
+							@Override
+							public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) throws IOException {
+								int count = dir.getNameCount();
+								if (count == 2) {
+									// e.g. /modules/java.base
+									java.nio.file.Path mod = dir.getName(1);
+									if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0 &&
+											JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
+										return FileVisitResult.SKIP_SUBTREE;
+									}
+									return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? 
+											FileVisitResult.CONTINUE : visitor.visitModule(mod);
+								}
+								if (dir == subdir || count < 3 || (notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
+									// We are dealing with a module or not client is not interested in packages
+									return FileVisitResult.CONTINUE;
+								}
+								return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
+							}
+
+							@Override
+							public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
+								if ((notify & JRTUtil.NOTIFY_FILES) == 0)
+									return FileVisitResult.CONTINUE;
+								int count = file.getNameCount();
+								// This happens when a file in a default package is present. E.g. /modules/some.module/file.name
+								if (count == 3) {
+									cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
+								}
+								return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
+							}
+						});
+					} else if (visitPackageMapping) {
+						Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
+							@Override
+							public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
+								// e.g. /modules/java.base
+								java.nio.file.Path relative = subdir.relativize(file);
+								cachePackage(relative.getParent().toString(), relative.getFileName().toString());
+								return FileVisitResult.CONTINUE;
+							}
+						});
+					}
+			    }
+			} catch (Exception e) {
+				throw new IOException(e.getMessage());
+			}
+		}
+	}
+
+	void cachePackage(String packageName, String module) {
+		packageName = packageName.intern();
+		module = module.intern();
+		packageName = packageName.replace('.', '/');
+		Object current = this.packageToModule.get(packageName);
+		if (current == null) {
+			this.packageToModule.put(packageName, module);
+		} else if(current == module || current.equals(module)) {
+			return;
+		} else if (current == JRTUtil.MULTIPLE) {
+			List<String> list = this.packageToModules.get(packageName);
+			if (!list.contains(module)) {
+				if (JRTUtil.JAVA_BASE == module || JRTUtil.JAVA_BASE.equals(module)) {
+					list.add(0, JRTUtil.JAVA_BASE);
+				} else {
+					list.add(module);
+				}
+			}
+		} else {
+			String first = (String) current;
+			this.packageToModule.put(packageName, JRTUtil.MULTIPLE);
+			List<String> list = new ArrayList<String>();
+			// Just do this as comparator might be overkill
+			if (JRTUtil.JAVA_BASE == current || JRTUtil.JAVA_BASE.equals(current)) {
+				list.add(first);
+				list.add(module);
+			} else {
+				list.add(module);
+				list.add(first);
+			}
+			this.packageToModules.put(packageName, list);
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
index 61b919b..5ae3006 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -15,6 +19,8 @@
 	public final static String EXTENSION_CLASS = "CLASS"; //$NON-NLS-1$
 	public final static String EXTENSION_java = "java"; //$NON-NLS-1$
 	public final static String EXTENSION_JAVA = "JAVA"; //$NON-NLS-1$
+	public final static String EXTENSION_jmod = "jmod"; //$NON-NLS-1$
+	public final static String EXTENSION_JMOD = "JMOD"; //$NON-NLS-1$
 
 	public final static String SUFFIX_STRING_class = "." + EXTENSION_class; //$NON-NLS-1$
 	public final static String SUFFIX_STRING_CLASS = "." + EXTENSION_CLASS; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 56a86ef..ef346ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -1,9 +1,13 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
@@ -18,6 +22,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -27,6 +32,8 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Properties;
+import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
@@ -35,8 +42,10 @@
 import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
+import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
 import org.eclipse.jdt.internal.compiler.batch.Main;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -232,6 +241,10 @@
 	public static final String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
 
 	public static final String EMPTY_STRING = new String(CharOperation.NO_CHAR);
+	/**
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final String COMMA_SEPARATOR = new String(CharOperation.COMMA_SEPARATOR);
 	public static final int[] EMPTY_INT_ARRAY= new int[0];
 
 	/**
@@ -742,6 +755,51 @@
 		}
 		return true; // it is neither a ".java" file nor a ".class" file, so this is a potential archive name
 	}
+	
+	public static final int ZIP_FILE = 0;
+	public static final int JMOD_FILE = 1;
+	
+	/**
+	 * Returns the kind of archive this file is. The format is one of
+	 * #ZIP_FILE or {@link #JMOD_FILE}
+	 */
+	public final static int archiveFormat(String name) {
+		int lastDot = name.lastIndexOf('.');
+		if (lastDot == -1)
+			return -1; // no file extension, it cannot be a zip archive name
+		if (name.lastIndexOf(File.separatorChar) > lastDot)
+			return -1; // dot was before the last file separator, it cannot be a zip archive name
+		int length = name.length();
+		int extensionLength = length - lastDot - 1;
+		
+		if (extensionLength == EXTENSION_java.length()) {
+			for (int i = extensionLength-1; i >=0; i--) {
+				if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_java.charAt(i)) {
+					break; // not a ".java" file, check ".class" file case below
+				}
+				if (i == 0) {
+					return -1; // it is a ".java" file, it cannot be a zip archive name
+				}
+			}
+		}
+		if (extensionLength == EXTENSION_class.length()) {
+			for (int i = extensionLength-1; i >=0; i--) {
+				if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_class.charAt(i)) {
+					return ZIP_FILE; // not a ".class" file, so this is a potential archive name
+				}
+			}
+			return -1; // it is a ".class" file, it cannot be a zip archive name
+		}
+		if (extensionLength == EXTENSION_jmod.length()) {
+			for (int i = extensionLength-1; i >=0; i--) {
+				if (Character.toLowerCase(name.charAt(length - extensionLength + i)) != EXTENSION_jmod.charAt(i)) {
+					return ZIP_FILE; // not a ".jmod" file, so this is a potential archive name
+				}
+			}
+			return JMOD_FILE;
+		}
+		return ZIP_FILE; // it is neither a ".java" file nor a ".class" file, so this is a potential archive name
+	}
 
 	/**
 	 * Returns true iff str.toLowerCase().endsWith(".class")
@@ -851,6 +909,14 @@
 		return true;
 	}
 
+	/**
+	 * Returns true iff str.toLowerCase().endsWith("jrt-fs.jar")
+	 * implementation is not creating extra strings.
+	 */
+	public final static boolean isJrt(String name) {
+		return name.endsWith(JRTUtil.JRT_FS_JAR);
+	}
+
 	public static void reverseQuickSort(char[][] list, int left, int right) {
 		int original_left= left;
 		int original_right= right;
@@ -1093,24 +1159,58 @@
 		return null;
 	}
 
-	public static void collectRunningVMBootclasspath(List bootclasspaths) {
-		for (String filePath : collectFilesNames()) {
-			FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null);
-			if (currentClasspath != null) {
-				bootclasspaths.add(currentClasspath);
-			}
-		}
+	public static void collectVMBootclasspath(List bootclasspaths, File javaHome) {
+		List<Classpath> classpaths = collectPlatformLibraries(javaHome);
+		bootclasspaths.addAll(classpaths);
 	}
-
-	public static List<String> collectFilesNames() {
+	public static void collectRunningVMBootclasspath(List bootclasspaths) {
+		collectVMBootclasspath(bootclasspaths, null);
+	}
+	public static long getJDKLevel(File javaHome) {
+		String version = getJavaVersion(javaHome);
+		return CompilerOptions.versionToJdkLevel(version);
+	}
+	public static String getJavaVersion(File javaHome) {
+		if (javaHome == null) {
+			return System.getProperty("java.version"); //$NON-NLS-1$
+		}
+		File release = new File(javaHome, "release"); //$NON-NLS-1$
+		Properties prop = new Properties();
+		try {
+			prop.load(new FileReader(release));
+			String ver = prop.getProperty("JAVA_VERSION"); //$NON-NLS-1$
+			if (ver != null)
+				ver = ver.replace("\"", "");  //$NON-NLS-1$//$NON-NLS-2$
+			return ver;
+		} catch (IOException e) {
+			// Nothing can be done.
+		}
+		return null;
+	}
+	public static List<FileSystem.Classpath> collectFilesNames() {
+		return collectPlatformLibraries(null);
+	}
+	public static List<FileSystem.Classpath> collectPlatformLibraries(File javaHome) {
 		/* no bootclasspath specified
 		 * we can try to retrieve the default librairies of the VM used to run
 		 * the batch compiler
 		 */
-		String javaversion = System.getProperty("java.version");//$NON-NLS-1$
+		String javaversion = null;
+		javaversion = getJavaVersion(javaHome);
 		if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
 			throw new IllegalStateException();
 		}
+		long jdkLevel = CompilerOptions.versionToJdkLevel(javaversion);
+		if (jdkLevel >= ClassFileConstants.JDK9) {
+			List<FileSystem.Classpath> filePaths = new ArrayList<>();
+			if (javaHome == null) {
+				javaHome = getJavaHome();
+			}
+			if (javaHome != null) {
+				filePaths.add(FileSystem.getJrtClasspath(javaHome.getAbsolutePath(), null, null, null));
+				return filePaths;
+			}
+		}
 
 		/*
 		 * Handle >= JDK 1.2.2 settings: retrieve the bootclasspath
@@ -1125,7 +1225,7 @@
 				bootclasspathProperty = System.getProperty("org.apache.harmony.boot.class.path"); //$NON-NLS-1$
 			}
 		}
-		List<String> filePaths = new ArrayList<>();
+		Set<String> filePaths = new HashSet<>();
 		if ((bootclasspathProperty != null) && (bootclasspathProperty.length() != 0)) {
 			StringTokenizer tokenizer = new StringTokenizer(bootclasspathProperty, File.pathSeparator);
 			while (tokenizer.hasMoreTokens()) {
@@ -1133,7 +1233,9 @@
 			}
 		} else {
 			// try to get all jars inside the lib folder of the java home
-			final File javaHome = getJavaHome();
+			if (javaHome == null) {
+				javaHome = getJavaHome();
+			}
 			if (javaHome != null) {
 				File[] directoriesToCheck = null;
 				if (System.getProperty("os.name").startsWith("Mac")) {//$NON-NLS-1$//$NON-NLS-2$
@@ -1159,7 +1261,14 @@
 				}
 			}
 		}
-		return filePaths;
+		List<FileSystem.Classpath> classpaths = new ArrayList<>();
+		for (String filePath : filePaths) {
+			FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null);
+			if (currentClasspath != null) {
+				classpaths.add(currentClasspath);
+			}
+		}
+		return classpaths;
 	}
 	public static int getParameterCount(char[] methodSignature) {
 		try {
@@ -1628,5 +1737,4 @@
 				}
 		}
 	}
-
 }
\ No newline at end of file
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 c262cec..a90205e 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -113,7 +117,7 @@
      * </p>
      *
 	 * @since 3.0
-	 * @deprecated Clients should use the {@link #JLS8} AST API instead.
+	 * @deprecated Clients should use the {@link #JLS9} AST API instead.
 	 */
 	public static final int JLS2 = 2;
 
@@ -137,7 +141,7 @@
      * </p>
      *
 	 * @since 3.1
-	 * @deprecated Clients should use the {@link #JLS8} AST API instead.
+	 * @deprecated Clients should use the {@link #JLS9} AST API instead.
 	 */
 	public static final int JLS3 = 3;
 	
@@ -161,7 +165,7 @@
 	 * </p>
 	 *
 	 * @since 3.7.1
-	 * @deprecated Clients should use the {@link #JLS8} AST API instead.
+	 * @deprecated Clients should use the {@link #JLS9} AST API instead.
 	 */
 	public static final int JLS4 = 4;
 	
@@ -185,9 +189,40 @@
 	 * </p>
 	 *
 	 * @since 3.10
+	 * @deprecated Clients should use the {@link #JLS9} AST API instead.
 	 */
 	public static final int JLS8 = 8;
 
+	/**
+	 * Internal synonym for {@link #JLS8}. Use to alleviate
+	 * deprecation warnings.
+	 * @since 3.13 BETA_JAVA9
+	 */
+	/*package*/ static final int JLS8_INTERNAL = JLS8;
+	
+	/**
+	 * Constant for indicating the AST API that handles JLS9.
+	 * <p>
+	 * This API is capable of handling all constructs in the
+	 * Java language as described in the Java Language
+	 * Specification, Java SE 9 Edition (JLS9).
+	 * JLS9 is a superset of all earlier versions of the
+	 * Java language, and the JLS9 API can be used to manipulate
+	 * programs written in all versions of the Java language
+	 * up to and including Java SE 9 (aka JDK 9).
+	 * </p>
+	 *
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int JLS9 = 9;
+
+	/**
+	 * Internal synonym for {@link #JLS9}. Use to alleviate
+	 * deprecation warnings once JLS9 is deprecated
+	 * @since 3.13 BETA_JAVA9
+	 */
+	/*package*/ static final int JLS9_INTERNAL = JLS9;
+
 	/*
 	 * Must not collide with a value for ICompilationUnit constants
 	 */
@@ -278,7 +313,7 @@
 	 * Creates a new Java abstract syntax tree
      * (AST) following the specified set of API rules.
      * <p>
-     * Clients should use this method specifying {@link #JLS8} as the
+     * Clients should use this method specifying {@link #JLS9} as the
      * AST level in all cases, even when dealing with source of earlier JDK versions like 1.3 or 1.4.
      * </p>
      *
@@ -658,8 +693,8 @@
 	 * Creates a new, empty abstract syntax tree using default options.
 	 *
 	 * @see JavaCore#getDefaultOptions()
-	 * @deprecated Clients should port their code to use the new JLS4 AST API and call
-	 *    {@link #newAST(int) AST.newAST(AST.JLS4)} instead of using this constructor.
+	 * @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.
 	 */
 	public AST() {
 		this(JavaCore.getDefaultOptions());
@@ -701,7 +736,7 @@
 						null/*taskPriorities*/,
 						true/*taskCaseSensitive*/);
 				break;
-			case JLS8 :
+			case JLS8_INTERNAL :
 				this.apiLevel = level;
 				// initialize a scanner
 				this.scanner = new Scanner(
@@ -714,6 +749,19 @@
 						null/*taskPriorities*/,
 						true/*taskCaseSensitive*/);
 				break;	
+			case JLS9 :
+				this.apiLevel = level;
+				// initialize a scanner
+				this.scanner = new Scanner(
+						true /*comment*/,
+						true /*whitespace*/,
+						false /*nls*/,
+						ClassFileConstants.JDK9   /*sourceLevel*/,
+						ClassFileConstants.JDK9 /*complianceLevel*/,
+						null/*taskTag*/,
+						null/*taskPriorities*/,
+						true/*taskCaseSensitive*/);
+				break;	
 			default:
 				throw new IllegalArgumentException("Unsupported JLS level"); //$NON-NLS-1$
 		}
@@ -740,8 +788,8 @@
 	 * @param options the table of options (key type: <code>String</code>;
 	 *    value type: <code>String</code>)
 	 * @see JavaCore#getDefaultOptions()
-	 * @deprecated Clients should port their code to use the new JLS4 AST API and call
-	 *    {@link #newAST(int) AST.newAST(AST.JLS4)} instead of using this constructor.
+	 * @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.
 	 */
 	public AST(Map options) {
 		this(JLS2);
@@ -1129,7 +1177,7 @@
 	 */
 	public ArrayType newArrayType(Type elementType) {
 		ArrayType result;
-		if (this.apiLevel < AST.JLS8) {
+		if (this.apiLevel < JLS8_INTERNAL) {
 			result = new ArrayType(this);
 			setArrayComponentType(result, elementType);
 			return result;
@@ -1173,7 +1221,7 @@
 			throw new IllegalArgumentException();
 		}
 		ArrayType result;
-		if (this.apiLevel < AST.JLS8) {
+		if (this.apiLevel < JLS8_INTERNAL) {
 			if (dimensions < 1) {
 				throw new IllegalArgumentException();
 			}
@@ -1461,10 +1509,23 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented exports statement
+	 * node for an unspecified, but legal, name; no target modules
+	 *
+	 * @return a new unparented exports statement node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public ExportsStatement newExportsStatement() {
+		ExportsStatement result = new ExportsStatement(this);
+		return result;
+	}
+
+	/**
 	 * Creates an unparented expression method reference node owned by this AST.
 	 * By default, the expression and method name are unspecified (but legal),
 	 * and there are no type arguments.
-	 * 
+	 *
 	 * @return a new unparented expression method reference expression node
 	 * @exception UnsupportedOperationException if this operation is used in a JLS2, JLS3 or JLS4 AST
 	 * @since 3.10
@@ -1881,6 +1942,20 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented module declaration
+	 * node for an unspecified, but legal, name; no modifiers; no javadoc;
+	 * and an empty list of statements.
+	 *
+	 * @return a new unparented module declaration node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public ModuleDeclaration newModuleDeclaration() {
+		ModuleDeclaration result = new ModuleDeclaration(this);
+		return result;
+	}
+
+	/**
 	 * Creates and returns a new unparented name node for the given name.
 	 * The name string must consist of 1 or more name segments separated
 	 * by single dots '.'. Returns a {@link QualifiedName} if the name has
@@ -2044,6 +2119,19 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented opens statement
+	 * node for an unspecified, but legal, name; no target modules
+	 *
+	 * @return a new unparented opens statement node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public OpensStatement newOpensStatement() {
+		OpensStatement result = new OpensStatement(this);
+		return result;
+	}
+
+	/**
 	 * Creates an unparented package declaration node owned by this AST.
 	 * The package declaration initially declares a package with an
 	 * unspecified name.
@@ -2127,6 +2215,19 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented provides statement
+	 * node for an unspecified, but legal, type; no target types
+	 *
+	 * @return a new unparented provides statement node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public ProvidesStatement newProvidesStatement() {
+		ProvidesStatement result = new ProvidesStatement(this);
+		return result;
+	}
+
+	/**
 	 * Creates and returns a new unparented qualified name node for the given
 	 * qualifier and simple name child node.
 	 *
@@ -2173,6 +2274,19 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented requires statement
+	 * node for an unspecified, but legal, name;
+	 *
+	 * @return a new unparented requires statement node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public RequiresStatement newRequiresStatement() {
+		RequiresStatement result = new RequiresStatement(this);
+		return result;
+	}
+
+	/**
 	 * Creates a new unparented return statement node owned by this AST.
 	 * By default, the return statement has no expression.
 	 *
@@ -2540,6 +2654,19 @@
 	}
 
 	/**
+	 * Creates and returns a new unparented uses statement
+	 * node for an unspecified, but legal, name;
+	 *
+	 * @return a new unparented uses statement node
+	 * @exception UnsupportedOperationException if this operation is used in level less than JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public UsesStatement newUsesStatement() {
+		UsesStatement result = new UsesStatement(this);
+		return result;
+	}
+
+	/**
 	 * Creates a new unparented intersection type node owned by this AST.
 	 * By default, the intersection type has no types.
 	 *
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 47ad175..ca150ed 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -13,11 +17,13 @@
 
 package org.eclipse.jdt.core.dom;
 
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
@@ -30,6 +36,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
 import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression;
@@ -37,6 +44,7 @@
 import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
 import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
 import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
@@ -471,7 +479,7 @@
 	protected void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
 		ArrayType array = arrayType;
 		this.recordNodes(arrayType, astNode);
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 			this.recordNodes(arrayType.getElementType(), astNode);
 			return;
 		}
@@ -515,7 +523,7 @@
 		int methodHeaderEnd = methodDeclaration.sourceEnd;
 		int thrownExceptionsLength = thrownExceptions == null ? 0 : thrownExceptions.length;
 		if (thrownExceptionsLength > 0) {
-			if (this.ast.apiLevel() < AST.JLS8) {
+			if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
 				Name thrownException;
 				int i = 0;
 				do {
@@ -539,7 +547,7 @@
 		}
 
 		if (methodDeclaration.receiver != null) {
-			if(this.ast.apiLevel >= AST.JLS8) {
+			if(this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				convertAndSetReceiver(methodDeclaration, methodDecl);
 			} else {
 				methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
@@ -585,7 +593,7 @@
 				// get the positions of the right parenthesis
 				int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd);
 				int extraDimensions = typeReference.extraDimensions();
-				if (this.ast.apiLevel >= AST.JLS8) {
+				if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 					setExtraAnnotatedDimensions(rightParenthesisPosition, method.bodyEnd, typeReference,
 												methodDecl.extraDimensions(), extraDimensions);
 				} else {
@@ -645,7 +653,7 @@
 			}
 			if (block != null) {
 				if ((methodDeclaration.modifiers & (ClassFileConstants.AccAbstract | ClassFileConstants.AccNative)) != 0
-						|| (isInterface && (this.ast.apiLevel < AST.JLS8 ||
+						|| (isInterface && (this.ast.apiLevel < AST.JLS8_INTERNAL ||
 							(methodDeclaration.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) == 0))) {
 					methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
 				}
@@ -908,7 +916,7 @@
 		final int typeSourceEnd = argument.type.sourceEnd;
 		TypeReference typeReference = argument.type;
 		final int extraDimensions = typeReference.extraDimensions();
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			setExtraAnnotatedDimensions(nameEnd + 1, typeSourceEnd, typeReference,
 										variableDecl.extraDimensions(), extraDimensions);
 		} else {
@@ -928,7 +936,7 @@
 		 */
 		if (isVarArgs) {
 			Dimension lastDimension = null;
-			if (this.ast.apiLevel() >= AST.JLS8) {
+			if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 				if (type.isArrayType()) { // should always be true
 					List dimensions = ((ArrayType) type).dimensions();
 					if (!dimensions.isEmpty()) {
@@ -938,7 +946,7 @@
 			}
 			setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
 			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898
-			if (this.ast.apiLevel() >= AST.JLS8) {
+			if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 				if (lastDimension != null) { // should always be true
 					List annotations = lastDimension.annotations();
 					Iterator iter = annotations.iterator();
@@ -1011,7 +1019,7 @@
 		if (type.isArrayType()) {
 			arrayType = (ArrayType) type;
 			if (expression.annotationsOnDimensions != null) {
-				if (this.ast.apiLevel() < AST.JLS8) {
+				if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
 					arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED);
 				} else {
 					setTypeAnnotationsAndSourceRangeOnArray(arrayType, expression.annotationsOnDimensions);
@@ -1363,24 +1371,37 @@
 				}
 			}
 	
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
-			if (types != null) {
-				int typesLength = types.length;
-				for (int i = 0; i < typesLength; i++) {
-					org.eclipse.jdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
-					if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
-						continue;
-					}
-					ASTNode type = convert(declaration);
-					if (type == null) {
-						compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
-					} else {
-						compilationUnit.types().add(type);
+			org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration mod = unit.moduleDeclaration;
+			if (mod != null) {
+				ASTNode declaration = convertToModuleDeclaration(mod);
+				if (declaration == null) {
+					compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+				} else {
+					compilationUnit.setModule((ModuleDeclaration) declaration);
+				}
+			} else {
+				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
+				if (types != null) {
+					int typesLength = types.length;
+					for (int i = 0; i < typesLength; i++) {
+						org.eclipse.jdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
+						if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
+							continue;
+						}
+						ASTNode type = convert(declaration);
+						if (type == null) {
+							compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+						} else {
+							if (type instanceof ModuleDeclaration)
+								compilationUnit.setModule((ModuleDeclaration) type);
+							else
+								compilationUnit.types().add(type);
+						}
 					}
 				}
 			}
 			compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart  + 1);
-	
+
 			int problemLength = unit.compilationResult.problemCount;
 			if (problemLength != 0) {
 				CategorizedProblem[] resizedProblems = null;
@@ -1679,6 +1700,28 @@
 		return newStatement;
 	}
 
+	private ModulePackageAccess getPackageVisibilityStatement(
+			org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement pvsStmt, ModulePackageAccess stmt) {
+		int sourceEnd = pvsStmt.declarationSourceEnd;
+		if (pvsStmt.declarationEnd > sourceEnd) sourceEnd = pvsStmt.declarationEnd; // TODO: working around a compiler issue
+		Name name = getImportName(pvsStmt.pkgRef);
+		stmt.setName(name);
+		if (this.resolveBindings) {
+			recordNodes(name, pvsStmt.pkgRef);
+		}
+		int tmp = sourceEnd;
+		if (pvsStmt.targets != null && pvsStmt.targets.length > 0) {
+			List<Name> modules = stmt.modules();
+			for (ModuleReference moduleRef : pvsStmt.getTargetedModules()) {
+				modules.add(getName(moduleRef, CharOperation.splitOn('.', moduleRef.moduleName), moduleRef.sourcePositions));
+				if (tmp < moduleRef.sourceEnd) tmp = moduleRef.sourceEnd;
+			}
+		}
+		if (tmp > sourceEnd) sourceEnd = tmp;
+		stmt.setSourceRange(pvsStmt.declarationSourceStart, sourceEnd - pvsStmt.declarationSourceStart + 1);			
+		return stmt;
+	}
+
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
 		if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
 			return convertToParenthesizedExpression(expression);
@@ -2000,54 +2043,50 @@
 		return literal;
 	}
 
-	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
-		if (bodyDeclaration.getJavadoc() == null) {
-			if (javadoc != null) {
-				if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
-					this.commentMapper = new DefaultCommentMapper(this.commentsTable);
-				}
-				Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
-				if (comment != null && comment.isDocComment() && comment.getParent() == null) {
-					Javadoc docComment = (Javadoc) comment;
-					if (this.resolveBindings) {
-						recordNodes(docComment, javadoc);
-						// resolve member and method references binding
-						Iterator tags = docComment.tags().listIterator();
-						while (tags.hasNext()) {
-							recordNodes(javadoc, (TagElement) tags.next());
-						}
+	interface IGetJavaDoc {
+		Javadoc getJavaDoc();
+	}
+	interface ISetJavaDoc {
+		void setJavadoc(Javadoc javadoc);
+	}
+	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, IGetJavaDoc getJ, ISetJavaDoc setJ) {
+		if (getJ.getJavaDoc() == null) {
+			Javadoc docComment = convert(javadoc);
+			if (docComment != null) 
+				setJ.setJavadoc(docComment);
+		}
+	}
+	private Javadoc convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc) {
+		Javadoc docComment = null;
+		if (javadoc != null) {
+			if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+				this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+			}
+			Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+			if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+				docComment = (Javadoc) comment;
+				if (this.resolveBindings) {
+					recordNodes(docComment, javadoc);
+					// resolve member and method references binding
+					Iterator tags = docComment.tags().listIterator();
+					while (tags.hasNext()) {
+						recordNodes(javadoc, (TagElement) tags.next());
 					}
-					bodyDeclaration.setJavadoc(docComment);
 				}
 			}
 		}
+		return docComment;
+	}
+	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
+		convert(javadoc, bodyDeclaration::getJavadoc, bodyDeclaration::setJavadoc);
+	}
+	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, ModuleDeclaration moduleDeclaration) {
+		convert(javadoc, moduleDeclaration::getJavadoc, moduleDeclaration::setJavadoc);
 	}
 
 	public void convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, PackageDeclaration packageDeclaration) {
-		switch(this.ast.apiLevel) {
-			case AST.JLS2_INTERNAL :
-				return;
-		}
-		if (packageDeclaration.getJavadoc() == null) {
-			if (javadoc != null) {
-				if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
-					this.commentMapper = new DefaultCommentMapper(this.commentsTable);
-				}
-				Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
-				if (comment != null && comment.isDocComment() && comment.getParent() == null) {
-					Javadoc docComment = (Javadoc) comment;
-					if (this.resolveBindings) {
-						recordNodes(docComment, javadoc);
-						// resolve member and method references binding
-						Iterator tags = docComment.tags().listIterator();
-						while (tags.hasNext()) {
-							recordNodes(javadoc, (TagElement) tags.next());
-						}
-					}
-					packageDeclaration.setJavadoc(docComment);
-				}
-			}
-		}
+		if (this.ast.apiLevel == AST.JLS2_INTERNAL) return;
+		convert(javadoc, packageDeclaration::getJavadoc, packageDeclaration::setJavadoc);
 	}
 
 	public LabeledStatement convert(org.eclipse.jdt.internal.compiler.ast.LabeledStatement statement) {
@@ -2210,7 +2249,7 @@
 	}
 
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambda) {
-		if (this.ast.apiLevel < AST.JLS8) {
+		if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
 			return createFakeNullLiteral(lambda);		
 		}
 		final LambdaExpression	lambdaExpression = new LambdaExpression(this.ast);
@@ -2568,7 +2607,7 @@
 	}
 
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression reference) {
-		if (this.ast.apiLevel < AST.JLS8) {
+		if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
 			return createFakeNullLiteral(reference);
 		}
 		Expression result = null;
@@ -2849,8 +2888,7 @@
 	public TryStatement convert(org.eclipse.jdt.internal.compiler.ast.TryStatement statement) {
 		final TryStatement tryStatement = new TryStatement(this.ast);
 		tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		LocalDeclaration[] localDeclarations = statement.resources;
-		int resourcesLength = localDeclarations.length;
+		int resourcesLength = statement.resources.length;
 		if (resourcesLength > 0) {
 			switch(this.ast.apiLevel) {
 				case AST.JLS2_INTERNAL :
@@ -2858,15 +2896,41 @@
 					// convert it to a simple try statement tagged as MALFORMED
 					tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED);
 					break;
-				default:
+				case AST.JLS4_INTERNAL:
+				case AST.JLS8_INTERNAL:
 					for (int i = 0; i < resourcesLength; i++) {
-						LocalDeclaration localDeclaration = localDeclarations[i];
+						if (!(statement.resources[i] instanceof LocalDeclaration)) {
+							tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED);
+							break;
+						}
+						LocalDeclaration localDeclaration = (LocalDeclaration)statement.resources[i];
 						VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(localDeclaration);
 						int start = variableDeclarationExpression.getStartPosition();
 						int end = localDeclaration.declarationEnd;
 						variableDeclarationExpression.setSourceRange(start, end - start + 1);
 						tryStatement.resources().add(variableDeclarationExpression);
 					}
+					break;
+				default:
+					for (int i = 0; i < resourcesLength; i++) {
+						org.eclipse.jdt.internal.compiler.ast.Statement resource = statement.resources[i];
+						if (resource instanceof LocalDeclaration) {
+							LocalDeclaration localDeclaration = (LocalDeclaration)resource;
+							VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(localDeclaration);
+							int start = variableDeclarationExpression.getStartPosition();
+							int end = localDeclaration.declarationEnd;
+							variableDeclarationExpression.setSourceRange(start, end - start + 1);
+							tryStatement.resources().add(variableDeclarationExpression);
+						} else if (resource instanceof NameReference) {
+							tryStatement.resources().add(convert((NameReference) resource));
+						} else if (resource instanceof FieldReference) {
+							tryStatement.resources().add(convert((FieldReference) resource));
+						} else {
+							tryStatement.setFlags(tryStatement.getFlags() | ASTNode.MALFORMED);
+							break;
+						}
+					}
+					break;
 			}
 		}
 		tryStatement.setBody(convert(statement.tryBlock));
@@ -3069,24 +3133,9 @@
 
 	public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
 		final ImportDeclaration importDeclaration = new ImportDeclaration(this.ast);
+		Name name = getImportName(importReference);
+		importDeclaration.setName(name);
 		final boolean onDemand = (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0;
-		final char[][] tokens = importReference.tokens;
-		int length = importReference.tokens.length;
-		final long[] positions = importReference.sourcePositions;
-		if (length > 1) {
-			importDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
-		} else {
-			final SimpleName name = new SimpleName(this.ast);
-			name.internalSetIdentifier(new String(tokens[0]));
-			final int start = (int)(positions[0]>>>32);
-			final int end = (int)(positions[0] & 0xFFFFFFFF);
-			name.setSourceRange(start, end - start + 1);
-			name.index = 1;
-			importDeclaration.setName(name);
-			if (this.resolveBindings) {
-				recordNodes(name, importReference);
-			}
-		}
 		importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
 		importDeclaration.setOnDemand(onDemand);
 		int modifiers = importReference.modifiers;
@@ -3109,6 +3158,30 @@
 		return importDeclaration;
 	}
 
+	public Name getImportName(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
+		return getName(importReference, importReference.tokens, importReference.sourcePositions);
+	}
+
+	private Name getName(org.eclipse.jdt.internal.compiler.ast.ASTNode node, final char[][] tokens,
+			final long[] positions) {
+		Name name;
+		int length = tokens != null ? tokens.length : 0;
+		if (length > 1) {
+			name = setQualifiedNameNameAndSourceRanges(tokens, positions, node);
+		} else {
+			name = new SimpleName(this.ast);
+			((SimpleName)name).internalSetIdentifier(new String(tokens[0]));
+			final int start = (int)(positions[0]>>>32);
+			final int end = (int)(positions[0] & 0xFFFFFFFF);
+			name.setSourceRange(start, end - start + 1);
+			name.index = 1;
+			if (this.resolveBindings) {
+				recordNodes(name, node);
+			}
+		}
+		return name;
+	}
+
 	public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
 		org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
 		final PackageDeclaration packageDeclaration = new PackageDeclaration(this.ast);
@@ -3153,7 +3226,7 @@
 	private ArrayType convertToArray(Type elementType, int sourceStart, int length, int dimensions, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions) {
 		ArrayType arrayType = this.ast.newArrayType(elementType, dimensions);
 		if (length > 0) arrayType.setSourceRange(sourceStart, length);
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
 			if (annotationsOnDimensions != null) {
 				arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED);
 			}
@@ -3223,6 +3296,84 @@
 		return fieldDeclaration;
 	}
 
+	public ModuleDeclaration convertToModuleDeclaration(org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration) {
+		checkCanceled();
+		if (this.scanner.sourceLevel < ClassFileConstants.JDK9) return null;
+		ModuleDeclaration moduleDecl = this.ast.newModuleDeclaration();
+		// TODO
+		//convert(moduleDeclaration.javadoc, moduleDecl);
+		setModifiers(moduleDecl, moduleDeclaration);
+		Name moduleName = getName(moduleDeclaration, CharOperation.splitOn('.', moduleDeclaration.moduleName), moduleDeclaration.sourcePositions);
+		moduleDecl.setName(moduleName);
+		moduleDecl.setSourceRange(moduleDeclaration.declarationSourceStart, moduleDeclaration.declarationSourceEnd - moduleDeclaration.declarationSourceStart + 1);
+
+		if (this.resolveBindings) {
+			this.recordNodes(moduleDecl, moduleDeclaration);
+		}
+		List<ModuleStatement> stmts = moduleDecl.moduleStatements();
+		TreeSet<ModuleStatement> tSet = new TreeSet<> (new Comparator() {
+			public int compare(Object o1, Object o2) {
+				int p1 = ((ModuleStatement) o1).getStartPosition();
+				int p2 = ((ModuleStatement) o2).getStartPosition();
+				return p1 < p2 ? -1 : p1 == p2 ? 0 : 1;
+			}
+		});
+		for (int i = 0; i < moduleDeclaration.exportsCount; ++i) {
+			tSet.add(getPackageVisibilityStatement(moduleDeclaration.exports[i], new ExportsStatement(this.ast)));
+		}
+		for (int i = 0; i < moduleDeclaration.opensCount; ++i) {
+			tSet.add(getPackageVisibilityStatement(moduleDeclaration.opens[i], new OpensStatement(this.ast)));
+		}
+		for (int i = 0; i < moduleDeclaration.requiresCount; ++i) {
+			org.eclipse.jdt.internal.compiler.ast.RequiresStatement req = moduleDeclaration.requires[i];
+			ModuleReference moduleRef = req.module;
+			RequiresStatement stmt = new RequiresStatement(this.ast);
+			Name name = getName(moduleRef, CharOperation.splitOn('.', moduleRef.moduleName), moduleRef.sourcePositions);
+			stmt.setName(name);
+
+			addModifierToRequires(req, req.isTransitive(), Modifier.ModifierKeyword.TRANSIENT_KEYWORD, stmt);
+			addModifierToRequires(req, req.isStatic(), Modifier.ModifierKeyword.STATIC_KEYWORD, stmt);
+			stmt.setSourceRange(req.declarationSourceStart, req.declarationEnd - req.declarationSourceStart + 1);			
+			tSet.add(stmt);
+		}
+		for (int i = 0; i < moduleDeclaration.usesCount; ++i) {
+			org.eclipse.jdt.internal.compiler.ast.UsesStatement usesStatement = moduleDeclaration.uses[i];
+			UsesStatement stmt = new UsesStatement(this.ast);
+			TypeReference usesRef = usesStatement.serviceInterface;
+			stmt.setType(convertType(usesRef));
+			stmt.setSourceRange(usesStatement.declarationSourceStart, usesStatement.declarationSourceEnd - usesStatement.declarationSourceStart + 1);			
+			tSet.add(stmt);
+		}
+		for (int i = 0; i < moduleDeclaration.servicesCount; ++i) {
+			org.eclipse.jdt.internal.compiler.ast.ProvidesStatement pStmt = moduleDeclaration.services[i];
+			ProvidesStatement stmt = new ProvidesStatement(this.ast);
+			stmt.setType(convertType(pStmt.serviceInterface));
+			TypeReference[] impls = pStmt.implementations;
+			for (TypeReference impl : impls) {
+				stmt.implementations().add(convertType(impl));
+			}
+			stmt.setSourceRange(pStmt.declarationSourceStart, pStmt.declarationSourceEnd - pStmt.declarationSourceStart + 1);			
+			tSet.add(stmt);
+		}
+		// The javadoc comment is now got from 	list store in compilation unit declaration
+		if (this.resolveBindings) {
+			recordNodes(moduleDecl, moduleDeclaration);
+			recordNodes(moduleName, moduleDeclaration);
+			// moduleDecl.resolveBinding(); TODO: Implement resolveBinding
+		}
+		stmts.addAll(tSet);
+		return moduleDecl;
+	}
+
+	private void addModifierToRequires(org.eclipse.jdt.internal.compiler.ast.RequiresStatement req, boolean flag, Modifier.ModifierKeyword keyword,
+			RequiresStatement stmt) {
+		if (flag) {
+			Modifier modifier = createModifier(keyword);
+			modifier.setSourceRange(req.modifiersSourceStart, keyword.toString().length());
+			stmt.modifiers().add(modifier);
+		}
+	}
+
 	public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
 		final ParenthesizedExpression parenthesizedExpression = new ParenthesizedExpression(this.ast);
 		if (this.resolveBindings) {
@@ -3266,7 +3417,7 @@
 		variableDecl.setName(name);
 		TypeReference typeReference = localDeclaration.type;
 		final int extraDimensions = typeReference.extraDimensions();
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			setExtraAnnotatedDimensions(nameEnd + 1, localDeclaration.declarationSourceEnd, typeReference,
 					variableDecl.extraDimensions(), extraDimensions);
 		} else {
@@ -3314,7 +3465,7 @@
 		int end = start;
 		TypeReference typeReference = fieldDeclaration.type;
 		int extraDimensions = typeReference.extraDimensions();
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			setExtraAnnotatedDimensions(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd,
 					typeReference, variableDeclarationFragment.extraDimensions(), extraDimensions);
 		} else {
@@ -3358,7 +3509,7 @@
 		org.eclipse.jdt.internal.compiler.ast.Expression initialization = localDeclaration.initialization;
 		TypeReference typeReference = localDeclaration.type;
 		int extraDimension = typeReference.extraDimensions();
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			setExtraAnnotatedDimensions(localDeclaration.sourceEnd + 1, this.compilationUnitSourceLength,
 					typeReference, variableDeclarationFragment.extraDimensions(), extraDimension);
 		} else {
@@ -3904,7 +4055,7 @@
 			}
 
 			boolean createNameQualifiedType = typeAnnotations != null && typeAnnotations[firstTypeIndex] != null;
-			if (createNameQualifiedType && this.ast.apiLevel >= AST.JLS8) {
+			if (createNameQualifiedType && this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				NameQualifiedType nameQualifiedType = new NameQualifiedType(this.ast);
 				nameQualifiedType.setQualifier(name);
 				nameQualifiedType.setName(createSimpleName(typeReference, positions, tokens, firstTypeIndex));
@@ -4242,7 +4393,6 @@
 		}
 		return false;
 	}
-
 	private void lookupForScopes() {
 		if (this.pendingNameScopeResolution != null) {
 			for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
@@ -4994,6 +5144,9 @@
 	 * @param bodyDeclaration
 	 */
 	protected void setModifiers(BodyDeclaration bodyDeclaration, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) {
+		setModifiers(bodyDeclaration.modifiers(), annotations, modifiersEnd);
+	}
+	protected void setModifiers(List modifiers, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) {
 		this.scanner.tokenizeWhiteSpace = false;
 		try {
 			int token;
@@ -5054,7 +5207,7 @@
 						break;
 				}
 				if (modifier != null) {
-					bodyDeclaration.modifiers().add(modifier);
+					modifiers.add(modifier);
 				}
 			}
 		} catch(InvalidInputException e) {
@@ -5134,6 +5287,10 @@
 		}
 	}
 
+	protected void setModifiers(ModuleDeclaration moduleDecl, org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration moduleDeclaration) {
+		this.scanner.resetTo(moduleDeclaration.declarationSourceStart, moduleDeclaration.sourceStart);
+		this.setModifiers(moduleDecl.modifiers(), moduleDeclaration.annotations, moduleDeclaration.sourceStart);
+	}
 	/**
 	 * @param variableDecl
 	 * @param argument
@@ -5629,7 +5786,7 @@
 				fieldDeclaration.setType(type);
 			}
 		} else {
-			if (type.isArrayType() && (this.ast.apiLevel() < AST.JLS8)) {
+			if (type.isArrayType() && (this.ast.apiLevel() < AST.JLS8_INTERNAL)) {
 				// update positions of the component types of the array type
 				int dimensions = ((ArrayType) type).getDimensions();
 				updateInnerPositions(type, dimensions);
@@ -5647,7 +5804,7 @@
 	private ArrayType extractSubArrayType(ArrayType arrayType, int remainingDimensions, int dimensionsToRemove) {
 		ArrayType subArrayType = arrayType;
 		int start = subArrayType.getStartPosition();
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
 			while (dimensionsToRemove > 0 ) {
 				subArrayType = (ArrayType) componentType(subArrayType);
 				dimensionsToRemove--;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
index 088f314..6eaac1d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -335,7 +339,7 @@
 		}
 		ArrayType o = (ArrayType) other;
 		int level = node.getAST().apiLevel;
-		if (level < AST.JLS8) {
+		if (level < AST.JLS8_INTERNAL) {
 			return safeSubtreeMatch(componentType(node), componentType(o));
 		}
 		return safeSubtreeMatch(node.getElementType(), o.getElementType())
@@ -615,7 +619,8 @@
 		}
 		CompilationUnit o = (CompilationUnit) other;
 		return (
-			safeSubtreeMatch(node.getPackage(), o.getPackage())
+			(node.getAST().apiLevel >= AST.JLS9_INTERNAL ? safeSubtreeMatch(node.getModule(), o.getModule()) : true)
+				&& safeSubtreeMatch(node.getPackage(), o.getPackage())
 				&& safeSubtreeListMatch(node.imports(), o.imports())
 				&& safeSubtreeListMatch(node.types(), o.types()));
 	}
@@ -887,6 +892,31 @@
 	 * @return <code>true</code> if the subtree matches, or
 	 *   <code>false</code> if they do not match or the other object has a
 	 *   different node type or is <code>null</code>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean match(ExportsStatement node, Object other) {
+		if (!(other instanceof ExportsStatement)) {
+			return false;
+		}
+		ExportsStatement o = (ExportsStatement) other;
+		return (
+			safeSubtreeMatch(node.getName(), o.getName())
+				&& safeSubtreeListMatch(node.modules(), o.modules()));
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
 	 * @since 3.10
 	 */
 	public boolean match(ExpressionMethodReference node, Object other) {
@@ -1474,12 +1504,12 @@
 								// n.b. compare return type even for constructors
 								&& safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType()))
 				&& safeSubtreeMatch(node.getName(), o.getName())
-				&& (level >= AST.JLS8
+				&& (level >= AST.JLS8_INTERNAL
 						? safeSubtreeMatch(node.getReceiverType(), o.getReceiverType())
 								&& safeSubtreeMatch(node.getReceiverQualifier(), o.getReceiverQualifier())
 						: true)
 				&& safeSubtreeListMatch(node.parameters(), o.parameters())
-				&& (level >= AST.JLS8
+				&& (level >= AST.JLS8_INTERNAL
 						? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions())
 								&& safeSubtreeListMatch(node.thrownExceptionTypes(), o.thrownExceptionTypes())
 						: node.getExtraDimensions() == o.getExtraDimensions()
@@ -1553,6 +1583,32 @@
 	 * @return <code>true</code> if the subtree matches, or
 	 *   <code>false</code> if they do not match or the other object has a
 	 *   different node type or is <code>null</code>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean match(ModuleDeclaration node, Object other) {
+		if (!(other instanceof ModuleDeclaration)) {
+			return false;
+		}
+		ModuleDeclaration o = (ModuleDeclaration) other;
+		return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+				&& safeSubtreeListMatch(node.modifiers(), o.modifiers())
+				&& safeSubtreeMatch(node.getName(), o.getName())
+				&& safeSubtreeListMatch(node.moduleStatements(), o.moduleStatements()));
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
 	 * @since 3.10
 	 */
 	public boolean match(NameQualifiedType node, Object other) {
@@ -1645,6 +1701,31 @@
 	 * @return <code>true</code> if the subtree matches, or
 	 *   <code>false</code> if they do not match or the other object has a
 	 *   different node type or is <code>null</code>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean match(OpensStatement node, Object other) {
+		if (!(other instanceof OpensStatement)) {
+			return false;
+		}
+		OpensStatement o = (OpensStatement) other;
+		return (
+			safeSubtreeMatch(node.getName(), o.getName())
+				&& safeSubtreeListMatch(node.modules(), o.modules()));
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
 	 */
 	public boolean match(PackageDeclaration node, Object other) {
 		if (!(other instanceof PackageDeclaration)) {
@@ -1776,7 +1857,7 @@
 		}
 		PrimitiveType o = (PrimitiveType) other;
 		int level = node.getAST().apiLevel;
-		return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
+		return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
 				&& node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode();
 	}
 
@@ -1793,6 +1874,32 @@
 	 * @return <code>true</code> if the subtree matches, or
 	 *   <code>false</code> if they do not match or the other object has a
 	 *   different node type or is <code>null</code>
+	 * @since 3.13 BETA_JAVA9
+
+	 */
+	public boolean match(ProvidesStatement node, Object other) {
+		if (!(other instanceof ProvidesStatement)) {
+			return false;
+		}
+		ProvidesStatement o = (ProvidesStatement) other;
+		return (
+				safeSubtreeMatch(node.getType(), o.getType())
+				&& safeSubtreeListMatch(node.implementations(), o.implementations()));
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
 	 */
 	public boolean match(QualifiedName node, Object other) {
 		if (!(other instanceof QualifiedName)) {
@@ -1825,7 +1932,32 @@
 		QualifiedType o = (QualifiedType) other;
 		int level = node.getAST().apiLevel;
 		return safeSubtreeMatch(node.getQualifier(), o.getQualifier())
-				&& (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
+				&& (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
+				&& safeSubtreeMatch(node.getName(), o.getName());
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
+	 *
+	 *   @since 3.13 BETA_JAVA9
+	 */
+	public boolean match(RequiresStatement node, Object other) {
+		if (!(other instanceof RequiresStatement)) {
+			return false;
+		}
+		RequiresStatement o = (RequiresStatement) other;
+		return safeSubtreeListMatch(node.modifiers(), o.modifiers())
 				&& safeSubtreeMatch(node.getName(), o.getName());
 	}
 
@@ -1893,7 +2025,7 @@
 		}
 		SimpleType o = (SimpleType) other;
 		int level = node.getAST().apiLevel;
-		return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
+		return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
 				&& safeSubtreeMatch(node.getName(), o.getName());
 	}
 
@@ -1949,14 +2081,14 @@
 						? safeSubtreeListMatch(node.modifiers(), o.modifiers())
 						: node.getModifiers() == o.getModifiers())
 				&& safeSubtreeMatch(node.getType(), o.getType())
-				&& (level >= AST.JLS8 && node.isVarargs()
+				&& (level >= AST.JLS8_INTERNAL && node.isVarargs()
 						? safeSubtreeListMatch(node.varargsAnnotations(), o.varargsAnnotations())
 						: true)
 				&& (level >= AST.JLS3_INTERNAL
 						? node.isVarargs() == o.isVarargs()
 						: true)
 				&& safeSubtreeMatch(node.getName(), o.getName())
-				&& ((level >= AST.JLS8)
+				&& ((level >= AST.JLS8_INTERNAL)
 						? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions())
 						: node.getExtraDimensions() == o.getExtraDimensions())
 				&& safeSubtreeMatch(node.getInitializer(), o.getInitializer());
@@ -2424,7 +2556,7 @@
 		}
 		TypeParameter o = (TypeParameter) other;
 		int level = node.getAST().apiLevel;
-		return (level >= AST.JLS8 ? safeSubtreeListMatch(node.modifiers(), o.modifiers()) : true)
+		return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.modifiers(), o.modifiers()) : true)
 				&& safeSubtreeMatch(node.getName(), o.getName())
 				&& safeSubtreeListMatch(node.typeBounds(), o.typeBounds());
 	}
@@ -2465,6 +2597,29 @@
 	 * @return <code>true</code> if the subtree matches, or
 	 *   <code>false</code> if they do not match or the other object has a
 	 *   different node type or is <code>null</code>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean match(UsesStatement node, Object other) {
+		if (!(other instanceof UnionType)) {
+			return false;
+		}
+		UsesStatement o = (UsesStatement) other;
+		return safeSubtreeMatch(node.getType(), o.getType());
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
 	 */
 	public boolean match(VariableDeclarationExpression node, Object other) {
 		if (!(other instanceof VariableDeclarationExpression)) {
@@ -2511,7 +2666,7 @@
 		VariableDeclarationFragment o = (VariableDeclarationFragment) other;
 		int level = node.getAST().apiLevel;
 		return safeSubtreeMatch(node.getName(), o.getName())
-				&& (level >= AST.JLS8
+				&& (level >= AST.JLS8_INTERNAL
 						? safeSubtreeListMatch(node.extraDimensions(), o.extraDimensions())
 						: node.getExtraDimensions() == o.getExtraDimensions())
 				&& safeSubtreeMatch(node.getInitializer(), o.getInitializer());
@@ -2596,7 +2751,7 @@
 		}
 		WildcardType o = (WildcardType) other;
 		int level = node.getAST().apiLevel;
-		return (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
+		return (level >= AST.JLS8_INTERNAL ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true)
 				&& node.isUpperBound() == o.isUpperBound()
 				&& safeSubtreeMatch(node.getBound(), o.getBound());
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index 73e9b9d..d1afb65 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -897,6 +901,53 @@
 	public static final int TYPE_METHOD_REFERENCE = 92;
 
 	/**
+	 * Node type constant indicating a node of type
+	 * <code>ModuleDeclaration</code>.
+	 * @see ModuleDeclaration
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int MODULE_DECLARATION = 93;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>ExportsStatement</code>.
+	 * @see ExportsStatement
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int EXPORTS_STATEMENT = 94;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>RequiresStatement</code>.
+	 * @see RequiresStatement
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int REQUIRES_STATEMENT = 95;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>UsesStatement</code>.
+	 * @see UsesStatement
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int USES_STATEMENT = 96;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>ProvidesStatement</code>.
+	 * @see ProvidesStatement
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int PROVIDES_STATEMENT = 97;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>OpensStatement</code>.
+	 * @see OpensStatement
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int OPENS_STATEMENT = 98;
+	/**
 	 * Returns the node class for the corresponding node type.
 	 *
 	 * @param nodeType AST node type
@@ -964,6 +1015,8 @@
 				return EnumConstantDeclaration.class;
 			case ENUM_DECLARATION :
 				return EnumDeclaration.class;
+			case EXPORTS_STATEMENT :
+				return ExportsStatement.class;
 			case EXPRESSION_METHOD_REFERENCE :
 				return ExpressionMethodReference.class;
 			case EXPRESSION_STATEMENT :
@@ -1010,6 +1063,8 @@
 				return MethodRefParameter.class;
 			case MODIFIER :
 				return Modifier.class;
+			case MODULE_DECLARATION :
+				return ModuleDeclaration.class;
 			case NAME_QUALIFIED_TYPE :
 				return NameQualifiedType.class;
 			case NORMAL_ANNOTATION :
@@ -1018,6 +1073,8 @@
 				return NullLiteral.class;
 			case NUMBER_LITERAL :
 				return NumberLiteral.class;
+			case OPENS_STATEMENT :
+				return OpensStatement.class;
 			case PACKAGE_DECLARATION :
 				return PackageDeclaration.class;
 			case PARAMETERIZED_TYPE :
@@ -1030,10 +1087,14 @@
 				return PrefixExpression.class;
 			case PRIMITIVE_TYPE :
 				return PrimitiveType.class;
+			case PROVIDES_STATEMENT :
+				return ProvidesStatement.class;
 			case QUALIFIED_NAME :
 				return QualifiedName.class;
 			case QUALIFIED_TYPE :
 				return QualifiedType.class;
+			case REQUIRES_STATEMENT :
+				return RequiresStatement.class;
 			case RETURN_STATEMENT :
 				return ReturnStatement.class;
 			case SIMPLE_NAME :
@@ -1082,6 +1143,8 @@
 				return TypeParameter.class;
 			case UNION_TYPE :
 				return UnionType.class;
+			case USES_STATEMENT :
+				return UsesStatement.class;
 			case VARIABLE_DECLARATION_EXPRESSION :
 				return VariableDeclarationExpression.class;
 			case VARIABLE_DECLARATION_FRAGMENT :
@@ -1964,18 +2027,33 @@
 	 * @since 3.10
 	 */
 	final void unsupportedIn2_3_4() {
-		if (this.ast.apiLevel < AST.JLS8) {
+		if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
 			throw new UnsupportedOperationException("Operation only supported in JLS8 and later AST"); //$NON-NLS-1$
 		}
 	}
-	
+
+	/**
+     * Checks that this AST operation is not used when
+     * building JLS2, JLS3, JLS4 or JLS8 level ASTs.
+     * <p>
+     * Use this method to prevent access to new properties that have been added in JLS9.
+     * </p>
+     *
+	 * @exception UnsupportedOperationException if this operation is used below JLS9
+	 * @since 3.13 BETA_JAVA9
+	 */
+	final void unsupportedBelow9() {
+		if (this.ast.apiLevel < AST.JLS9_INTERNAL) {
+			throw new UnsupportedOperationException("Operation only supported in JLS9 and later AST"); //$NON-NLS-1$
+		}
+	}
 	/**
      * Checks that this AST operation is only used when
      * building JLS2 level ASTs.
      * <p>
      * Use this method to prevent access to deprecated properties (deprecated in JLS3).
      * </p>
-     * 
+     *
 	 * @exception UnsupportedOperationException if this operation is used in an AST later than JLS2
 	 * @since 3.0
      */
@@ -1998,7 +2076,7 @@
      */
 	// In API Javadocs, add: * @deprecated In the JLS8 API, this method is replaced by {@link #replacement()}.
 	final void supportedOnlyIn2_3_4() {
-	  if (this.ast.apiLevel >= AST.JLS8) {
+	  if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 	  	throw new UnsupportedOperationException("Operation only supported in JLS2, JLS3 and JLS4 ASTs"); //$NON-NLS-1$
 	  }
 	}
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 70a6e25..2de8224 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -226,7 +230,8 @@
 			case AST.JLS2_INTERNAL:
 			case AST.JLS3_INTERNAL:
 			case AST.JLS4_INTERNAL:
-			case AST.JLS8:
+			case AST.JLS8_INTERNAL:
+			case AST.JLS9_INTERNAL:
 				break;
 			default:
 				throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
index 9e86e96..96270f6 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2014 IBM Corporation and others.
+ * Copyright (c) 2006, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -51,6 +55,8 @@
 		this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
 		this.endingTokens.put(MethodDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON});
 		this.endingTokens.put(MethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+		this.endingTokens.put(ModuleDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+		this.endingTokens.put(ModuleStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
 		this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull});
 		this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral});
 		this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
@@ -192,6 +198,7 @@
 				case ASTNode.IMPORT_DECLARATION:
 				case ASTNode.INITIALIZER:
 				case ASTNode.METHOD_DECLARATION:
+				case ASTNode.MODULE_DECLARATION:
 				case ASTNode.PACKAGE_DECLARATION:
 				case ASTNode.TYPE_DECLARATION:
 				case ASTNode.MARKER_ANNOTATION:
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
index 8590672..f3d462e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -97,6 +101,13 @@
 	}
 
 	/*
+	 * Module declared on ASTVisitor.
+	 */
+	public boolean visit(ModuleDeclaration node) {
+		return checkAndTagAsMalformed(node);
+	}
+
+	/*
 	 * Method declared on ASTVisitor.
 	 */
 	public boolean visit(PackageDeclaration node) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
index d902b9b..2e04d57 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -655,6 +659,23 @@
 	 * @return <code>true</code> if the children of this node should be
 	 * visited, and <code>false</code> if the children of this node should
 	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(ExportsStatement node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
+	 * Subclasses may re-implement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
 	 * @since 3.10
 	 */
 	public boolean visit(ExpressionMethodReference node) {
@@ -1052,6 +1073,23 @@
 	 * @return <code>true</code> if the children of this node should be
 	 * visited, and <code>false</code> if the children of this node should
 	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(ModuleDeclaration node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
+	 * Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
 	 * @since 3.10
 	 */
 	public boolean visit(NameQualifiedType node) {
@@ -1111,6 +1149,23 @@
 	 * Visits the given type-specific AST node.
 	 * <p>
 	 * The default implementation does nothing and return true.
+	 * Subclasses may re-implement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(OpensStatement node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
 	 * Subclasses may reimplement.
 	 * </p>
 	 *
@@ -1192,6 +1247,23 @@
 	 * Visits the given type-specific AST node.
 	 * <p>
 	 * The default implementation does nothing and return true.
+	 * Subclasses may re-implement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(ProvidesStatement node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
 	 * Subclasses may reimplement.
 	 * </p>
 	 *
@@ -1241,6 +1313,23 @@
 	 * Visits the given type-specific AST node.
 	 * <p>
 	 * The default implementation does nothing and return true.
+	 * Subclasses may re-implement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(RequiresStatement node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
 	 * Subclasses may reimplement.
 	 * </p>
 	 *
@@ -1637,6 +1726,23 @@
 	 * Visits the given type-specific AST node.
 	 * <p>
 	 * The default implementation does nothing and return true.
+	 * Subclasses may re-implement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public boolean visit(UsesStatement node) {
+		return true;
+	}
+
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
 	 * Subclasses may reimplement.
 	 * </p>
 	 *
@@ -2057,6 +2163,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(ExportsStatement node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 * @since 3.10
 	 */
 	public void endVisit(ExpressionMethodReference node) {
@@ -2348,6 +2467,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(ModuleDeclaration node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 * @since 3.10
 	 */
 	public void endVisit(NameQualifiedType node) {
@@ -2398,6 +2530,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(OpensStatement node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 */
 	public void endVisit(PackageDeclaration node) {
 		// default implementation: do nothing
@@ -2471,6 +2616,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(ProvidesStatement node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 */
 	public void endVisit(QualifiedName node) {
 		// default implementation: do nothing
@@ -2496,6 +2654,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(RequiresStatement node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 */
 	public void endVisit(ReturnStatement node) {
 		// default implementation: do nothing
@@ -2791,6 +2962,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void endVisit(UsesStatement node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 * @since 3.10
 	 */
 	public void endVisit(IntersectionType node) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java
index 4d33f98..626f177 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -75,7 +75,7 @@
 	 */
 	AnnotatableType(AST ast) {
 		super(ast);
-		if (ast.apiLevel >= AST.JLS8) {
+		if (ast.apiLevel >= AST.JLS8_INTERNAL) {
 			this.annotations = new ASTNode.NodeList(getAnnotationsProperty());
 		}
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
index 0e8f6db..38a92fb 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2011 BEA Systems, Inc.
+ * Copyright (c) 2005, 2017 BEA Systems, Inc, IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *    tyeung@bea.com - initial API and implementation
  *    IBM Corporation - implemented methods from IBinding
@@ -132,6 +136,11 @@
 				if (methodBinding == null) return null;
 				parentElement = methodBinding.getJavaElement();
 			break;
+/*		case ASTNode.MODULE_DECLARATION:  TODO: Enable after bug 515875 enables module binding
+			IModuleBinding moduleBinding = ((ModuleDeclaration) parent).resolveBinding();
+			if (moduleBinding == null) return null;
+			parentElement = moduleBinding.getJavaElement();
+		break;*/
 		case ASTNode.VARIABLE_DECLARATION_STATEMENT:
 			fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) parent).fragments().get(0);
 			variableBinding = fragment.resolveBinding();
@@ -178,6 +187,8 @@
 			return fragment.resolveBinding().getKey();
 		case ASTNode.METHOD_DECLARATION:
 			return ((MethodDeclaration) recipient).resolveBinding().getKey();
+/*		case ASTNode.MODULE_DECLARATION: //TODO: Enable after bug 515875 enable module binding
+			return ((ModuleDeclaration) recipient).resolveBinding().getKey();*/
 		case ASTNode.VARIABLE_DECLARATION_STATEMENT:
 			fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) recipient).fragments().get(0);
 			return fragment.resolveBinding().getKey();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
index 7c4f63b..6873d00 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
@@ -144,7 +144,7 @@
 	 */
 	ArrayType(AST ast) {
 		super(ast);
-		if (ast.apiLevel >= AST.JLS8) {
+		if (ast.apiLevel >= AST.JLS8_INTERNAL) {
 			this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY);
 			// single dimension array is the default
 			this.dimensions().add(this.ast.newDimension());
@@ -224,7 +224,7 @@
 	 */
 	ASTNode clone0(AST target) {
 		ArrayType result;
-		if (this.ast.apiLevel < AST.JLS8) {
+		if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
 			result = new ArrayType(target);
 			result.setComponentType((Type) getComponentType().clone(target));			
 		} else {
@@ -252,7 +252,7 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
-			if (this.ast.apiLevel < AST.JLS8) {
+			if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
 				acceptChild(visitor, getComponentType());				
 			} else {
 				acceptChild(visitor, getElementType());
@@ -332,7 +332,7 @@
 	 * @return the element type node
 	 */
 	public Type getElementType() {
-		if (this.ast.apiLevel() < AST.JLS8) {
+		if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
 			Type t = getComponentType();
 			while (t.isArrayType()) {
 				t = ((ArrayType) t).getComponentType();
@@ -376,7 +376,7 @@
 	 * @return the number of dimensions (always positive)
 	 */
 	public int getDimensions() {
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 			return dimensions().size();
 		}
 		Type t = getComponentType();
@@ -419,7 +419,7 @@
 	int treeSize() {
 		return
 			memSize()
-			+ (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8 ? getComponentType().treeSize() : getElementType().treeSize())
+			+ (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8_INTERNAL ? getComponentType().treeSize() : getElementType().treeSize())
 			+ (this.dimensions == null ? 0 : this.dimensions.listSize()));
 	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
index f3d1ddc..69f3bcb 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -28,6 +32,8 @@
 
 /**
  * Java compilation unit AST node type. This is the type of the root of an AST.
+ * From JLS 9 onwards, this can contain a ModuleDeclation. To be noted that not
+ * all nodes make sense in all contexts.
  * <p>
  * The source range for this type of node is ordinarily the entire source file,
  * including leading and trailing whitespace and comments.
@@ -36,7 +42,7 @@
  * CompilationUnit:
  *    [ PackageDeclaration ]
  *        { ImportDeclaration }
- *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | <b>;</b> }
+ *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | ModuleDeclaration <b>;</b> }
  * </pre>
  *
  * @since 2.0
@@ -72,6 +78,14 @@
 		new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
 
 	/**
+	 * The "module" structural property of this node type (child type: {@link ModuleDeclaration}) (added in JLS9 API).
+	 *
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final ChildPropertyDescriptor MODULE_PROPERTY =
+		new ChildPropertyDescriptor(CompilationUnit.class, "module", ModuleDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
 	 * A list of property descriptors (element type:
 	 * {@link StructuralPropertyDescriptor}),
 	 * or null if uninitialized.
@@ -80,6 +94,14 @@
 	private static final List PROPERTY_DESCRIPTORS;
 
 	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 * @since 3.13 BETA_JAVA9
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	/**
 	 * The "types" structural property of this node type (element type: {@link AbstractTypeDeclaration}).
 	 *
 	 * @since 3.0
@@ -94,6 +116,14 @@
 		addProperty(IMPORTS_PROPERTY, properyList);
 		addProperty(TYPES_PROPERTY, properyList);
 		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+
+		properyList = new ArrayList(5);
+		createPropertyList(CompilationUnit.class, properyList);
+		addProperty(PACKAGE_PROPERTY, properyList);
+		addProperty(IMPORTS_PROPERTY, properyList);
+		addProperty(TYPES_PROPERTY, properyList);
+		addProperty(MODULE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
 	}
 
 	/**
@@ -108,7 +138,10 @@
 	 * @since 3.0
 	 */
 	public static List propertyDescriptors(int apiLevel) {
-		return PROPERTY_DESCRIPTORS;
+		if (apiLevel < AST.JLS9_INTERNAL)
+			return PROPERTY_DESCRIPTORS;
+		else
+			return PROPERTY_DESCRIPTORS_9_0;
 	}
 
 	/**
@@ -168,10 +201,15 @@
 	private PackageDeclaration optionalPackageDeclaration = null;
 
 	/**
+	 * The module declaration, or <code>null</code> if none; initially
+	 * <code>null</code>.
+	 */
+	private ModuleDeclaration module = null;
+	/**
 	 * Problems reported by the compiler during parsing or name resolution.
 	 */
 	private IProblem[] problems = EMPTY_PROBLEMS;
-	
+
 	/**
 	 * Internal data used to perform statements recovery.
 	 */
@@ -207,6 +245,9 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
+			if (this.ast.apiLevel >= AST.JLS9_INTERNAL) {
+				acceptChild(visitor, getModule());
+			}
 			acceptChild(visitor, getPackage());
 			acceptChildren(visitor, this.imports);
 			acceptChildren(visitor, this.types);
@@ -221,6 +262,9 @@
 		CompilationUnit result = new CompilationUnit(target);
 		// n.b do not copy line number table or messages
 		result.setSourceRange(getStartPosition(), getLength());
+		if (this.ast.apiLevel >= AST.JLS9_INTERNAL) {
+			result.setModule((ModuleDeclaration) ASTNode.copySubtree(target, getModule()));
+		}
 		result.setPackage(
 			(PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
 		result.imports().addAll(ASTNode.copySubtrees(target, imports()));
@@ -537,6 +581,18 @@
 	}
 
 	/**
+	 * Returns the node for the module declaration of this compilation
+	 * unit, or <code>null</code> if this compilation unit is not a module info.
+	 *
+	 * @return the module declaration node, or <code>null</code> if none
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public ModuleDeclaration getModule() {
+		unsupportedBelow9();
+		return this.module;
+	}
+
+	/**
 	 * Returns the node for the package declaration of this compilation
 	 * unit, or <code>null</code> if this compilation unit is in the
 	 * default package.
@@ -716,6 +772,14 @@
 	 * Method declared on ASTNode.
 	 */
 	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == MODULE_PROPERTY) {
+			if (get) {
+				return getModule();
+			} else {
+				setModule((ModuleDeclaration) child);
+				return null;
+			}
+		}
 		if (property == PACKAGE_PROPERTY) {
 			if (get) {
 				return getPackage();
@@ -1000,6 +1064,26 @@
 	}
 
 	/**
+	 * Sets or clears the module declaration of this compilation unit
+	 * node to the given module declaration node.
+	 *
+	 * @param module the new module declaration node, or
+	 *   <code>null</code> if this compilation unit does not have a module
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public void setModule(ModuleDeclaration module) {
+		ASTNode oldChild = this.module;
+		preReplaceChild(oldChild, module, PACKAGE_PROPERTY);
+		this.module = module;
+		postReplaceChild(oldChild, module, PACKAGE_PROPERTY);
+	}
+
+	/**
 	 * Sets or clears the package declaration of this compilation unit
 	 * node to the given package declaration node.
 	 *
@@ -1058,6 +1142,9 @@
 	 */
 	int treeSize() {
 		int size = memSize();
+		if (this.module != null) {
+			size += getModule().treeSize();
+		}
 		if (this.optionalPackageDeclaration != null) {
 			size += getPackage().treeSize();
 		}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
index 326f071..ac3f05e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -183,6 +187,12 @@
 	public void endVisit(Modifier node) {
 		endVisitNode(node);
 	}
+	public void endVisit(ModuleDeclaration node) {
+		endVisitNode(node);
+	}
+	public void endVisit(ModuleStatement node) {
+		endVisitNode(node);
+	}
 	public void endVisit(NameQualifiedType node) {
 		endVisitNode(node);
 	}
@@ -468,6 +478,12 @@
 	public boolean visit(Modifier node) {
 		return visitNode(node);
 	}
+	public boolean visit(ModuleDeclaration node) {
+		return visitNode(node);
+	}
+	public boolean visit(ModuleStatement node) {
+		return visitNode(node);
+	}
 	public boolean visit(MethodRefParameter node) {
 		return visitNode(node);
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 6e07687..3794765 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -1155,6 +1159,8 @@
 				}
 			}
 		} else if (node instanceof ImportReference) {
+			if ((node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.inModule) != 0)
+				return null;
 			ImportReference importReference = (ImportReference) node;
 			int importReferenceLength = importReference.tokens.length;
 			if (index >= 0) {
@@ -1373,10 +1379,11 @@
 		} else if (node instanceof ImportReference) {
 			ImportReference importReference = (ImportReference) node;
 			int importReferenceLength = importReference.tokens.length;
+			boolean inModule = (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.inModule) != 0;
 			if (index >= 0) {
 				Binding binding = null;
 				if (this.scope == null) return null;
-				if (importReferenceLength == index) {
+				if (importReferenceLength == index && !inModule) {
 					try {
 						binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
 					} catch (AbortCompilation e) {
@@ -1384,7 +1391,7 @@
 					}
 				} else {
 					try {
-						binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
+						binding = this.scope.getImport(inModule ? importReference.tokens : CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
 					} catch (AbortCompilation e) {
 						// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
 					}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
index 6bb5390..9f5dc88 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
@@ -144,7 +144,7 @@
 				}
 			}
 			argument.setType(argType);
-			if (this.ast.apiLevel > AST.JLS8) {
+			if (this.ast.apiLevel > AST.JLS8_INTERNAL) {
 				argument.setVarargs(isVarargs);
 			}
 			argument.setSourceRange(argStart, argEnd - argStart + 1);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsStatement.java
new file mode 100644
index 0000000..9af5e11
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExportsStatement.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Exports statement AST node type.
+ * <pre>
+ * ExportsStatement:
+ *     <b>exports</b> PackageName [ <b>to</b>  ModuleName {<b>,</b> ModuleName } ] <b>;</b>
+ * </pre>
+ *
+ * @since 3.13 BETA_JAVA9
+ * 
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings({"rawtypes"})
+public class ExportsStatement extends ModulePackageAccess {
+
+	/**
+	 * The "package" structural property of this node type (child type: {@link Name}).
+	 */
+	public static final ChildPropertyDescriptor NAME_PROPERTY =
+			internalNamePropertyFactory(ExportsStatement.class);
+
+	/**
+	 * The "target" structural property of this node type (element type: {@link Name}).
+	 */
+	public static final ChildListPropertyDescriptor MODULES_PROPERTY =
+			internalModulesPropertyFactory(ExportsStatement.class);
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List properyList = new ArrayList(3);
+		createPropertyList(ExportsStatement.class, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(MODULES_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * Creates a new AST node for an export statement owned by the
+	 * given AST. The export statement initially is a regular (non-targetted)
+	 * single package export for an unspecified, but legal, Java package name.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	ExportsStatement(AST ast) {
+		super(ast);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final ChildPropertyDescriptor internalNameProperty() {
+		return NAME_PROPERTY;
+	}
+
+	@Override
+	final ChildListPropertyDescriptor internalModulesProperty() {
+		return MODULES_PROPERTY;
+	}
+
+	@Override
+	final int getNodeType0() {
+		return EXPORTS_STATEMENT;
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		return cloneHelper(target, new ExportsStatement(target));
+	}
+
+	@Override
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		acceptVisitChildren(visitChildren, visitor);
+		visitor.endVisit(this);
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
index c8eedbf..88fce6c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
@@ -254,7 +254,7 @@
 	public static List propertyDescriptors(int apiLevel) {
 		if (apiLevel == AST.JLS2_INTERNAL) {
 			return PROPERTY_DESCRIPTORS_2_0;
-		} else if (apiLevel < AST.JLS8) {
+		} else if (apiLevel < AST.JLS8_INTERNAL) {
 			return PROPERTY_DESCRIPTORS_3_0;
 		} else {
 			return PROPERTY_DESCRIPTORS_8_0;
@@ -379,7 +379,7 @@
 		if (ast.apiLevel >= AST.JLS3_INTERNAL) {
 			this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
 		}
-		if (ast.apiLevel < AST.JLS8) {
+		if (ast.apiLevel < AST.JLS8_INTERNAL) {
 			this.thrownExceptions = new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
 		} else {
 			this.extraDimensions = new ASTNode.NodeList(EXTRA_DIMENSIONS2_PROPERTY);
@@ -575,18 +575,18 @@
 		}
 		result.setConstructor(isConstructor());
 		result.setName((SimpleName) getName().clone(target));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.setReceiverType((Type) ASTNode.copySubtree(target, getReceiverType()));
 			result.setReceiverQualifier((SimpleName) ASTNode.copySubtree(target, getReceiverQualifier()));
 		}
 		result.parameters().addAll(
 			ASTNode.copySubtrees(target, parameters()));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.extraDimensions().addAll(ASTNode.copySubtrees(target, extraDimensions()));
 		} else {
 			result.setExtraDimensions(getExtraDimensions());
 		}
-		if (this.ast.apiLevel() >= AST.JLS8) {
+		if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 			result.thrownExceptionTypes().addAll(ASTNode.copySubtrees(target, thrownExceptionTypes()));
 		} else {
 			result.thrownExceptions().addAll(ASTNode.copySubtrees(target, thrownExceptions()));			
@@ -621,12 +621,12 @@
 			}
 			// n.b. visit return type even for constructors
 			acceptChild(visitor, getName());
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChild(visitor, this.optionalReceiverType);
 				acceptChild(visitor, this.optionalReceiverQualifier);
 			}
 			acceptChildren(visitor, this.parameters);
-			if (this.ast.apiLevel() >= AST.JLS8) {
+			if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.extraDimensions);
 				acceptChildren(visitor, this.thrownExceptionTypes);				
 			} else {
@@ -1169,7 +1169,7 @@
 			+ (this.optionalReceiverQualifier == null ? 0 : this.optionalReceiverQualifier.treeSize())
 			+ (this.returnType == null ? 0 : this.returnType.treeSize())
 			+ this.parameters.listSize()
-			+ (this.ast.apiLevel < AST.JLS8
+			+ (this.ast.apiLevel < AST.JLS8_INTERNAL
 					? this.thrownExceptions.listSize()
 					: this.extraDimensions.listSize() + this.thrownExceptionTypes.listSize())
 			+ (this.optionalBody == null ? 0 : getBody().treeSize());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java
new file mode 100644
index 0000000..e4d2afc
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleDeclaration.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Module declaration AST node type representing the module descriptor file
+ *
+ * <pre>
+ * ModuleDeclaration:
+ *  [ Javadoc ] { ExtendedModifier } <b>module</b> Name <b>{</b>
+ *        [ ExportsStatement | OpensStatement | RequiresStatement | UsesStatement | ProvidesStatement ]
+ *  <b>}</b>
+ * </pre>
+ * <p>
+ * </p>
+ *
+ * @since 3.13 BETA_JAVA9
+ * 
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings("rawtypes")
+public class ModuleDeclaration extends ASTNode {
+
+	/**
+	 * The "javadoc" structural property of this node type (child type: {@link Javadoc}).
+	 */
+	public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+			new ChildPropertyDescriptor(ModuleDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * The "modifiers" structural property of this node type (element type: {@link IExtendedModifier}).
+	 */
+	public static final ChildListPropertyDescriptor MODIFIERS_PROPERTY =
+			new ChildListPropertyDescriptor(ModuleDeclaration.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * The "name" structural property of this node type (child type: {@link Name}).
+	 */
+	public static final ChildPropertyDescriptor NAME_PROPERTY =
+		new ChildPropertyDescriptor(ModuleDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * The "moduleStatements" structural property of this node type (element type: {@link ModuleStatement}).
+	 */
+	public static final ChildListPropertyDescriptor MODULE_STATEMENTS_PROPERTY =
+		new ChildListPropertyDescriptor(ModuleDeclaration.class, "moduleStatements", ModuleStatement.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List properyList = new ArrayList(5);
+		createPropertyList(ModuleDeclaration.class, properyList);
+		addProperty(JAVADOC_PROPERTY, properyList);
+		addProperty(MODIFIERS_PROPERTY, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(MODULE_STATEMENTS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * The doc comment, or <code>null</code> if none.
+	 * Defaults to none.
+	 */
+	private Javadoc optionalDocComment = null;
+
+	/**
+	 * The extended modifiers (element type: {@link IExtendedModifier}).
+	 * defaults to an empty list
+	 * (see constructor).
+	 *
+	 */
+	private ASTNode.NodeList modifiers = null;
+
+	/**
+	 * The referenced module name; lazily initialized; defaults to a unspecified,
+	 * legal Java identifier.
+	 */
+	private Name name = null;
+
+	/**
+	 * The list of statements (element type: {@link ModuleStatement}).
+	 * Defaults to an empty list.
+	 */
+	private ASTNode.NodeList moduleStatements = new ASTNode.NodeList(MODULE_STATEMENTS_PROPERTY);
+
+	ModuleDeclaration(AST ast) {
+		super(ast);
+		unsupportedBelow9();
+		this.modifiers = new ASTNode.NodeList(MODIFIERS_PROPERTY);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 */
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == JAVADOC_PROPERTY) {
+			if (get) {
+				return getJavadoc();
+			} else {
+				setJavadoc((Javadoc) child);
+				return null;
+			}
+		}
+		if (property == NAME_PROPERTY) {
+			if (get) {
+				return getName();
+			} else {
+				setName((Name) child);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 */
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == MODIFIERS_PROPERTY) {
+			return modifiers();
+		}
+		if (property == MODULE_STATEMENTS_PROPERTY) {
+			return moduleStatements();
+		}
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	@Override
+	int getNodeType0() {
+		return MODULE_DECLARATION;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	ASTNode clone0(AST target) {
+		ModuleDeclaration result = new ModuleDeclaration(target);
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+		result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+		result.setName((SimpleName) getName().clone(target));
+		result.moduleStatements().addAll(ASTNode.copySubtrees(target, moduleStatements()));
+		return result;
+	}
+
+	@Override
+	boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		if (visitChildren) {
+			// visit children in normal left to right reading order
+			acceptChild(visitor, getJavadoc());
+			acceptChildren(visitor, this.modifiers);
+			acceptChild(visitor, getName());
+			acceptChildren(visitor, this.moduleStatements);
+		}
+		visitor.endVisit(this);
+
+	}
+	/**
+	 * Returns the doc comment node.
+	 *
+	 * @return the doc comment node, or <code>null</code> if none
+	 */
+	public Javadoc getJavadoc() {
+		return this.optionalDocComment;
+	}
+
+	/**
+	 * Sets or clears the doc comment node.
+	 *
+	 * @param docComment the doc comment node, or <code>null</code> if none
+	 * @exception IllegalArgumentException if the doc comment string is invalid
+	 */
+	public void setJavadoc(Javadoc docComment) {
+		ChildPropertyDescriptor p = JAVADOC_PROPERTY;
+		ASTNode oldChild = this.optionalDocComment;
+		preReplaceChild(oldChild, docComment, p);
+		this.optionalDocComment = docComment;
+		postReplaceChild(oldChild, docComment, p);
+	}
+
+	/**
+	 * Returns the modifiers explicitly specified on this declaration.
+	 * <p>
+	 *  this method is a convenience method that
+	 * computes these flags from {@link #modifiers()}.
+	 * </p>
+	 *
+	 * @return the bit-wise "or" of <code>Modifier</code> constants
+	 * @see Modifier
+	 */
+	public int getModifiers() {
+		// convenience method -
+		// performance could be improved by caching computed flags
+		// but this would require tracking changes to this.modifiers
+		int computedmodifierFlags = Modifier.NONE;
+		for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+			Object x = it.next();
+			if (x instanceof Modifier) {
+				computedmodifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+			}
+		}
+		return computedmodifierFlags;
+	}
+
+	/**
+	 * Returns the name of this module declaration.
+	 *
+	 * @return the module name
+	 */
+	public Name getName()  {
+		if (this.name == null) {
+			// lazy init must be thread-safe for readers
+			synchronized (this) {
+				if (this.name == null) {
+					preLazyInit();
+					this.name =this.ast.newQualifiedName(
+							new SimpleName(this.ast), new SimpleName(this.ast));
+					postLazyInit(this.name, NAME_PROPERTY);
+				}
+			}
+		}
+		return this.name;
+	}
+
+	/**
+	 * Sets the module name in to the given name.
+	 *
+	 * @param name the new module name
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */
+	public void setName(Name name) {
+		if (name == null) {
+			throw new IllegalArgumentException();
+		}
+		ASTNode oldChild = this.name;
+		preReplaceChild(oldChild, name, NAME_PROPERTY);
+		this.name = name;
+		postReplaceChild(oldChild, name, NAME_PROPERTY);
+	}
+
+	/**
+	 * Returns the live ordered list of modifiers and annotations
+	 * of this declaration.
+	 *
+	 * @return the live list of modifiers and annotations
+	 *    (element type: {@link IExtendedModifier})
+	 */
+	public List modifiers() {
+		return this.modifiers;
+	}
+
+	/**
+	 * Returns the live list of statements in this module. Adding and
+	 * removing nodes from this list affects this node dynamically.
+	 * All nodes in this list must be <code>Statement</code>s;
+	 * attempts to add any other type of node will trigger an
+	 * exception.
+	 *
+	 * @return the live list of statements in this module declaration
+	 *    (element type: {@link ModuleStatement})
+	 */
+	public List moduleStatements() {
+		return this.moduleStatements;
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 4 * 4;
+	}
+
+	@Override
+	int treeSize() {
+		return	memSize()
+			+ (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+			+ this.modifiers.listSize()
+			+ (this.name == null ? 0 : getName().treeSize())
+			+ this.moduleStatements.listSize();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java
new file mode 100644
index 0000000..4dae45a
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModulePackageAccess.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+
+/**
+ * Abstract base class of AST nodes that represent exports and opens statements.
+ *
+ * <pre>
+ * ModuleStatement: [ {@link ExportsStatement} |
+ *    {@link OpensStatement} ]
+ * </pre>
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ * @since 3.13 BETA_JAVA9
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public abstract class ModulePackageAccess extends ModuleStatement {
+
+	/**
+	 * The package name; lazily initialized; defaults to a unspecified,
+	 * legal Java identifier.
+	 */
+	protected Name name = null;
+
+	/**
+	 * The target modules
+	 * (element type: {@link Name}).
+	 * Defaults to an empty list. (see constructor)
+	 */
+	protected ASTNode.NodeList modules = null;
+
+	/**
+	 * Returns structural property descriptor for the "modules" property
+	 * of this node (element type: {@link Name}).
+	 *
+	 * @return the property descriptor
+	 */
+	abstract ChildListPropertyDescriptor internalModulesProperty();
+
+	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node (child type: {@link Name}).
+	 *
+	 * @return the property descriptor
+	 */
+	abstract ChildPropertyDescriptor internalNameProperty();
+
+	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node (child type: {@link Name}).
+	 *
+	 * @return the property descriptor
+	 */
+	public final ChildPropertyDescriptor getNameProperty() {
+		return internalNameProperty();
+	}
+
+	/**
+	 * Creates and returns a structural property descriptor for the
+	 * "name" property declared on the given concrete node type (child type: {@link Name}).
+	 *
+	 * @return the property descriptor
+	 */
+	static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) {
+		return new ChildPropertyDescriptor(nodeClass, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+	}
+
+	/**
+	 * Creates and returns a structural property descriptor for the
+	 * "modules" property declared on the given concrete node type (element type: {@link Name}).
+	 *
+	 * @return the property descriptor
+	 */
+	static final ChildListPropertyDescriptor internalModulesPropertyFactory(Class nodeClass) {
+		return new ChildListPropertyDescriptor(nodeClass, "modules", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+	}
+
+	/**
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	ModulePackageAccess(AST ast) {
+		super(ast);
+		this.modules = new ASTNode.NodeList(internalModulesProperty());
+	}
+
+	@Override
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == internalNameProperty()) {
+			if (get) {
+				return getName();
+			} else {
+				setName((Name) child);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	@Override
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == internalModulesProperty()) {
+			return modules();
+		}
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	/**
+	 * Returns the name of the package
+	 *
+	 * @return the package name node
+	 */
+	public Name getName()  {
+		if (this.name == null) {
+			// lazy init must be thread-safe for readers
+			synchronized (this) {
+				if (this.name == null) {
+					preLazyInit();
+					this.name =this.ast.newQualifiedName(
+							new SimpleName(this.ast), new SimpleName(this.ast));
+					ChildPropertyDescriptor p = internalNameProperty();
+					postLazyInit(this.name, p);
+				}
+			}
+		}
+		return this.name;
+	}
+
+	/**
+	 * Sets the name of the package to the given name.
+	 *
+	 * @param name the new  package name
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */
+	public void setName(Name name) {
+		if (name == null) {
+			throw new IllegalArgumentException();
+		}
+		ASTNode oldChild = this.name;
+		ChildPropertyDescriptor p = internalNameProperty();
+		preReplaceChild(oldChild, name, p);
+		this.name = name;
+		postReplaceChild(oldChild, name, p);
+	}
+
+	/**
+	 * Returns the live ordered list of target modules for this
+	 * statement.
+	 *
+	 * @return the live list of target modules
+	 *    (element type: {@link Name})
+	 */
+	public List modules() {
+		return this.modules;
+	}
+
+	protected ASTNode cloneHelper(AST target, ModulePackageAccess result) {
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setName((Name) getName().clone(target));
+		result.modules().addAll(ASTNode.copySubtrees(target, modules()));
+		return result;
+	}
+
+	protected void acceptVisitChildren(boolean visitChildren, ASTVisitor visitor) {
+		if (visitChildren) {
+			acceptChild(visitor, getName());
+			acceptChildren(visitor, this.modules);
+		}
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 2 * 4;
+	}
+
+	@Override
+	int treeSize() {
+		return
+			memSize()
+			+ (this.name == null ? 0 : getName().treeSize())
+			+ this.modules.listSize();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleStatement.java
new file mode 100644
index 0000000..97e2514
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ModuleStatement.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent module statements.
+ * There are many kinds of module statements.
+ *
+ * <pre>
+ * ModuleStatement: [ {@link ExportsStatement} |
+ *    {@link RequiresStatement} |
+ *    {@link UsesStatement} |
+ *    {@link ProvidesStatement} ]
+ * </pre>
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ * @since 3.13 BETA_JAVA9
+ */
+public abstract class ModuleStatement extends ASTNode {
+
+	ModuleStatement(AST ast) {
+		super(ast);
+		unsupportedBelow9();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java
index e05f7ca..2207f62 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NameEnvironmentWithProgress.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -12,12 +16,17 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.function.Function;
+import java.util.stream.Stream;
+
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.batch.ClasspathDirectory;
 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
 import org.eclipse.jdt.internal.core.NameLookup;
@@ -41,31 +50,53 @@
 			throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
 		}
 	}
-
-	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
-		return findType(typeName, packageName, true);
+	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext context) {
+		return findType(typeName, packageName, true, context);
 	}
-
-	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) {
+	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchSecondaryTypes, IModuleContext context) {
 		checkCanceled();
-		NameEnvironmentAnswer answer = super.findType(typeName, packageName);
-		if (answer == null && searchWithSecondaryTypes) {
-			NameEnvironmentAnswer suggestedAnswer = null;
+		NameEnvironmentAnswer answer = super.findType(typeName, packageName, context);
+		if (answer == null && searchSecondaryTypes) {
+//			NameEnvironmentAnswer suggestedAnswer = null;
 			String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
 			String qualifiedTypeName = new String(CharOperation.concatWith(packageName, typeName, '/'));
 			String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
-			for (int i = 0, length = this.classpaths.length; i < length; i++) {
-				if (!(this.classpaths[i] instanceof ClasspathDirectory)) continue;
-				ClasspathDirectory classpathDirectory = (ClasspathDirectory) this.classpaths[i];
-				answer = classpathDirectory.findSecondaryInClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
-				if (answer != null) {
-					if (!answer.ignoreIfBetter()) {
-						if (answer.isBetter(suggestedAnswer))
-							return answer;
-					} else if (answer.isBetter(suggestedAnswer))
-						// remember suggestion and keep looking
-						suggestedAnswer = answer;
-				}
+//			for (int i = 0, length = this.classpaths.length; i < length; i++) {
+//				if (!(this.classpaths[i] instanceof ClasspathDirectory)) continue;
+//				ClasspathDirectory classpathDirectory = (ClasspathDirectory) this.classpaths[i];
+//				for (IModule iModule : modules) {
+//					if (!classpathDirectory.servesModule(iModule.name())) continue;
+//					answer = classpathDirectory.findSecondaryInClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
+//					if (answer != null) {
+//						if (!answer.ignoreIfBetter()) {
+//							if (answer.isBetter(suggestedAnswer))
+//								return answer;
+//						} else if (answer.isBetter(suggestedAnswer))
+//							// remember suggestion and keep looking
+//							suggestedAnswer = answer;
+//					}
+//				}
+//			}
+			Function<ClasspathDirectory, ITypeLookup> secondaryTypesLookup = d -> {
+				return (t, qPackageName, qBinaryFileName,asBinaryOnly) -> {
+					return d.findSecondaryInClass(t, qPackageName, qBinaryFileName);
+				};
+			};
+			if (IModuleContext.UNNAMED_MODULE_CONTEXT == context) {
+				answer =  Stream.of(this.classpaths)
+						.filter(env -> env instanceof ClasspathDirectory)
+						.map(p -> (ClasspathDirectory)p)
+						.map(secondaryTypesLookup)
+						.reduce(ITypeLookup::chain)
+						.map(t -> t.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName)).orElse(null);
+			} else {
+				answer = context.getEnvironment()
+						.filter(env -> env instanceof ClasspathDirectory)
+						.map(p -> (ClasspathDirectory)p)
+						.map(secondaryTypesLookup)
+						.reduce(ITypeLookup::chain)
+						.map(lookup -> lookup.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName))
+						.orElse(null);
 			}
 		}
 		return answer;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensStatement.java
new file mode 100644
index 0000000..06d48aa
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/OpensStatement.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * opens statement AST node type.
+ * <pre>
+ * OpensStatement:
+ *     <b>opens</b> PackageName [ <b>to</b>  ModuleName {<b>,</b> ModuleName } ] <b>;</b>
+ * </pre>
+ *
+ * @since 3.13 BETA_JAVA9
+ * 
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings({"rawtypes"})
+public class OpensStatement extends ModulePackageAccess {
+
+	/**
+	 * The "package" structural property of this node type (child type: {@link Name}).
+	 */
+	public static final ChildPropertyDescriptor NAME_PROPERTY =
+		internalNamePropertyFactory(OpensStatement.class);
+	/**
+	 * The "target" structural property of this node type (element type: {@link Name}).
+	 */
+	public static final ChildListPropertyDescriptor MODULES_PROPERTY =
+			internalModulesPropertyFactory(OpensStatement.class);
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List properyList = new ArrayList(3);
+		createPropertyList(OpensStatement.class, properyList);
+		addProperty(NAME_PROPERTY, properyList);
+		addProperty(MODULES_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * Creates a new AST node for an opens statement owned by the
+	 * given AST. The open statement initially is a regular (non-targetted)
+	 * single package open for an unspecified, but legal, Java package name.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	OpensStatement(AST ast) {
+		super(ast);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final ChildPropertyDescriptor internalNameProperty() {
+		return NAME_PROPERTY;
+	}
+
+	@Override
+	final ChildListPropertyDescriptor internalModulesProperty() {
+		return MODULES_PROPERTY;
+	}
+
+	@Override
+	final int getNodeType0() {
+		return OPENS_STATEMENT;
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		return cloneHelper(target, new OpensStatement(target));
+	}
+
+	@Override
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		acceptVisitChildren(visitChildren, visitor);
+		visitor.endVisit(this);
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
index cf5a4af..24d8ce8 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
index 93fc3e6..f2ee622 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PrimitiveType.java
@@ -285,7 +285,7 @@
 	ASTNode clone0(AST target) {
 		PrimitiveType result = new PrimitiveType(target);
 		result.setSourceRange(getStartPosition(), getLength());
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.annotations().addAll(
 					ASTNode.copySubtrees(target, annotations()));
 		}
@@ -308,7 +308,7 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.annotations);
 			}
 		}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesStatement.java
new file mode 100644
index 0000000..acc2a90
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ProvidesStatement.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides statement AST node type.
+ * <pre>
+ * ProvidesStatement:
+ *     <b>provides</b> Name <b>with</b> Name {<b>,</b> Name } <b>;</b>
+ * </pre>
+ *
+ * @since 3.13 BETA_JAVA9
+ * 
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ProvidesStatement extends ModuleStatement {
+
+	/**
+	 * The "interface type" structural property of this node type (child type: {@link Type}).
+	 */
+	public static final ChildPropertyDescriptor TYPE_PROPERTY =
+		new ChildPropertyDescriptor(ProvidesStatement.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * The "implementation type" structural property of this node type (element type: {@link Type}).
+	 */
+	public static final ChildListPropertyDescriptor IMPLEMENTATIONS_PROPERTY =
+			new ChildListPropertyDescriptor(ProvidesStatement.class, "implementationType", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List properyList = new ArrayList(3);
+		createPropertyList(ProvidesStatement.class, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		addProperty(IMPLEMENTATIONS_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * The interface name; lazily initialized; defaults to a unspecified,
+	 * legal Java identifier.
+	 */
+	private Type type = null;
+
+	/**
+	 * The implementation names
+	 * (element type: {@link Name}).
+	 * Defaults to an empty list.
+	 */
+	private ASTNode.NodeList implementations =
+		new ASTNode.NodeList(IMPLEMENTATIONS_PROPERTY);
+
+	/**
+	 * Creates a new AST node for an provides statement owned by the
+	 * given AST. The provides statement initially is
+	 * for an unspecified, but legal, Java type name.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	ProvidesStatement(AST ast) {
+		super(ast);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == TYPE_PROPERTY) {
+			if (get) {
+				return getType();
+			} else {
+				setType((Type) child);
+				return null;
+			}
+		}
+
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	@Override
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == IMPLEMENTATIONS_PROPERTY) {
+			return implementations();
+		}
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	@Override
+	final int getNodeType0() {
+		return PROVIDES_STATEMENT;
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		ProvidesStatement result = new ProvidesStatement(target);
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setType((Type) getType().clone(target));
+		result.implementations().addAll(ASTNode.copySubtrees(target, implementations()));
+		return result;
+	}
+
+	@Override
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		if (visitChildren) {
+			acceptChild(visitor, getType());
+			acceptChildren(visitor, this.implementations);
+		}
+		visitor.endVisit(this);
+	}
+
+
+	/**
+	 * Returns the type name in this statement
+	 *
+	 * @return the type name
+	 */
+	public Type getType()  {
+		if (this.type == null) {
+			// lazy init must be thread-safe for readers
+			synchronized (this) {
+				if (this.type == null) {
+					preLazyInit();
+					this.type =this.ast.newPrimitiveType(PrimitiveType.INT);
+					postLazyInit(this.type, TYPE_PROPERTY);
+				}
+			}
+		}
+		return this.type;
+	}
+
+	/**
+	 * Sets the target module name in exports declaration to the given name.
+	 *
+	 * @param type the new target module name
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */
+	public void setType(Type type) {
+		if (type == null) {
+			throw new IllegalArgumentException();
+		}
+		ASTNode oldChild = this.type;
+		preReplaceChild(oldChild, type, TYPE_PROPERTY);
+		this.type = type;
+		postReplaceChild(oldChild, type, TYPE_PROPERTY);
+	}
+
+	/**
+	 * Returns the live ordered list of implementations for the interface in this provides statement.
+	 *
+	 * @return the live list of implementations for the interface
+	 *    (element type: {@link Name})
+	 */
+	public List implementations() {
+		return this.implementations;
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 2 * 4;
+	}
+
+	@Override
+	int treeSize() {
+		return
+			memSize()
+			+ (this.type == null ? 0 : getType().treeSize())
+			+ this.implementations.listSize();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
index 9ea8dcc..37a3284 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedType.java
@@ -231,7 +231,7 @@
 		QualifiedType result = new QualifiedType(target);
 		result.setSourceRange(getStartPosition(), getLength());
 		result.setQualifier((Type) ((ASTNode) getQualifier()).clone(target));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.annotations().addAll(
 					ASTNode.copySubtrees(target, annotations()));
 		}
@@ -255,7 +255,7 @@
 		if (visitChildren) {
 			// visit children in normal left to right reading order
 			acceptChild(visitor, getQualifier());
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.annotations);
 			}
 			acceptChild(visitor, getName());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresStatement.java
new file mode 100644
index 0000000..abebef4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RequiresStatement.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Requires statement AST node type.
+ * <pre>
+ * RequiresStatement:
+ *     <b>requires</b> { ExtendedModifier } Name <b>;</b>
+ * </pre>
+ *
+ * @since 3.13 BETA_JAVA9
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class RequiresStatement extends ModuleStatement {
+
+	/**
+	 * The "modifiers" structural property of this node type (element type: {@link IExtendedModifier}).
+	 */
+	public static final ChildListPropertyDescriptor MODIFIERS_PROPERTY =
+		new ChildListPropertyDescriptor(RequiresStatement.class, "modifiers", IExtendedModifier.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * The module structural property of this node type (child type: {@link Name}).
+	 */
+	public static final ChildPropertyDescriptor NAME_PROPERTY =
+		new ChildPropertyDescriptor(RequiresStatement.class, "name", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List propertyList = new ArrayList(3);
+		createPropertyList(RequiresStatement.class, propertyList);
+		addProperty(MODIFIERS_PROPERTY, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * The extended modifiers (element type: {@link IExtendedModifier}).
+	 * defaults to an empty list
+	 */
+	private ASTNode.NodeList modifiers = new ASTNode.NodeList(MODIFIERS_PROPERTY);
+
+	/**
+	 * The referenced module name; lazily initialized; defaults to a unspecified,
+	 * legal Java identifier.
+	 */
+	private Name name = null;
+
+	/**
+	 * Creates a new AST node for an requires statement owned by the
+	 * given AST. The requires statement initially is a regular (no modifiers)
+	 * requires for an unspecified, but legal, Java module name.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	RequiresStatement(AST ast) {
+		super(ast);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == NAME_PROPERTY) {
+			if (get) {
+				return getName();
+			} else {
+				setName((Name) child);
+				return null;
+			}
+		}
+
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	@Override
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == MODIFIERS_PROPERTY) {
+			return modifiers();
+		}
+
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	@Override
+	final int getNodeType0() {
+		return REQUIRES_STATEMENT;
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		RequiresStatement result = new RequiresStatement(target);
+		result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+		result.setName((Name) getName().clone(target));
+		return result;
+	}
+
+	@Override
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		if (visitChildren) {
+			acceptChildren(visitor, this.modifiers);
+			acceptChild(visitor, getName());
+		}
+		visitor.endVisit(this);
+	}
+
+	/**
+	 * Returns the live ordered list of modifiers
+	 * of this declaration.
+	 * <p>
+	 * Note that the not all modifiers are legal.
+	 * </p>
+	 *
+	 * @return the live list of modifiers
+	 *    (element type: {@link IExtendedModifier})
+	 */
+	public List modifiers() {
+		return this.modifiers;
+	}
+
+	/**
+	 * Returns the modifiers explicitly specified on this declaration.
+	 * <p>
+	 * this method is a convenience method that
+	 * computes these flags from <code>modifiers()</code>.
+	 * </p>
+	 *
+	 * @return the bit-wise or of <code>Modifier</code> constants
+	 * @see Modifier
+	 */
+	public int getModifiers() {
+		// do not cache - performance could be improved by caching computed flags
+		// but this would require tracking changes to this.modifiers
+		int computedModifierFlags = Modifier.NONE;
+		for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+			Object x = it.next();
+			if (x instanceof Modifier) {
+				computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+			}
+		}
+		return computedModifierFlags;
+	}
+
+	/**
+	 * Returns the module name referenced by this declaration.
+	 *
+	 * @return the module referenced
+	 */
+	public Name getName()  {
+		if (this.name == null) {
+			// lazy init must be thread-safe for readers
+			synchronized (this) {
+				if (this.name == null) {
+					preLazyInit();
+					this.name =this.ast.newQualifiedName(
+							new SimpleName(this.ast), new SimpleName(this.ast));
+					postLazyInit(this.name, NAME_PROPERTY);
+				}
+			}
+		}
+		return this.name;
+	}
+
+	/**
+	 * Sets the module name in requires statement to the given name.
+	 *
+	 * @param name the new module name
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */
+	public void setName(Name name) {
+		if (name == null) {
+			throw new IllegalArgumentException();
+		}
+		ASTNode oldChild = this.name;
+		preReplaceChild(oldChild, name, NAME_PROPERTY);
+		this.name = name;
+		postReplaceChild(oldChild, name, NAME_PROPERTY);
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 2 * 4;
+	}
+
+	@Override
+	int treeSize() {
+		return
+			memSize()
+			+ (this.modifiers == null ? 0 : this.modifiers.listSize())
+			+ (this.name == null ? 0 : getName().treeSize());
+	}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
index 33d123d..77370b7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
@@ -174,7 +174,7 @@
 	ASTNode clone0(AST target) {
 		SimpleType result = new SimpleType(target);
 		result.setSourceRange(getStartPosition(), getLength());
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.annotations().addAll(
 					ASTNode.copySubtrees(target, annotations()));
 		}
@@ -197,7 +197,7 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.annotations);
 			}
 			acceptChild(visitor, getName());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
index 99ca7a1..187ad5f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
@@ -171,7 +171,7 @@
 	public static List propertyDescriptors(int apiLevel) {
 		if (apiLevel == AST.JLS2_INTERNAL) {
 			return PROPERTY_DESCRIPTORS_2_0;
-		} else if (apiLevel < AST.JLS8) {
+		} else if (apiLevel < AST.JLS8_INTERNAL) {
 			return PROPERTY_DESCRIPTORS_3_0;
 		} else {
 			return PROPERTY_DESCRIPTORS_8_0;
@@ -231,7 +231,7 @@
 		super(ast);
 		if (ast.apiLevel >= AST.JLS3_INTERNAL) {
 			this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
-			if (ast.apiLevel >= AST.JLS8) {
+			if (ast.apiLevel >= AST.JLS8_INTERNAL) {
 				this.varargsAnnotations = new ASTNode.NodeList(VARARGS_ANNOTATIONS_PROPERTY);
 			}
 		}
@@ -385,12 +385,12 @@
 			result.setVarargs(isVarargs());
 		}
 		result.setType((Type) getType().clone(target));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.varargsAnnotations().addAll(
 					ASTNode.copySubtrees(target, varargsAnnotations()));
 		}
 		result.setName((SimpleName) getName().clone(target));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.extraDimensions().addAll(
 					ASTNode.copySubtrees(target, this.extraDimensions()));
 		} else {
@@ -420,11 +420,11 @@
 				acceptChildren(visitor, this.modifiers);
 			}
 			acceptChild(visitor, getType());
-			if (this.ast.apiLevel >= AST.JLS8 && isVarargs()) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL && isVarargs()) {
 				acceptChildren(visitor, this.varargsAnnotations);
 			}
 			acceptChild(visitor, getName());
-			if (this.ast.apiLevel >= AST.JLS8){
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL){
 				acceptChildren(visitor, this.extraDimensions);
 			}
 			acceptChild(visitor, getInitializer());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
index e6ce04f..cf65b03 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TryStatement.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -28,20 +32,31 @@
  * Not all node arrangements will represent legal Java constructs. In particular,
  * at least one resource, catch clause, or finally block must be present.</p>
  * 
+ * <p>A resource is either a {@link VariableDeclarationExpression} or (since JLS9) a {@link Name}.</p>
+ * 
  * @since 2.0
  * @noinstantiate This class is not intended to be instantiated by clients.
  */
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class TryStatement extends Statement {
 
+	
 	/**
 	 * The "resources" structural property of this node type (element type: {@link VariableDeclarationExpression}) (added in JLS4 API).
+	 * @deprecated In the JLS9 API, this property is replaced by {@link #RESOURCES2_PROPERTY}.
 	 * @since 3.7.1
 	 */
 	public static final ChildListPropertyDescriptor RESOURCES_PROPERTY =
 		new ChildListPropertyDescriptor(TryStatement.class, "resources", VariableDeclarationExpression.class, CYCLE_RISK); //$NON-NLS-1$
 
 	/**
+	 * The "resources" structural property of this node type (element type: {@link Expression}) (added in JLS9 API).
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final ChildListPropertyDescriptor RESOURCES2_PROPERTY =
+		new ChildListPropertyDescriptor(TryStatement.class, "resources", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+	/**
 	 * The "body" structural property of this node type (child type: {@link Block}).
 	 * @since 3.0
 	 */
@@ -77,6 +92,14 @@
 	 */
 	private static final List PROPERTY_DESCRIPTORS_4_0;
 
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 * @since 3.12_BETA_JAVA9
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
 	static {
 		List propertyList = new ArrayList(4);
 		createPropertyList(TryStatement.class, propertyList);
@@ -92,6 +115,14 @@
 		addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
 		addProperty(FINALLY_PROPERTY, propertyList);
 		PROPERTY_DESCRIPTORS_4_0 = reapPropertyList(propertyList);
+
+		propertyList = new ArrayList(5);
+		createPropertyList(TryStatement.class, propertyList);
+		addProperty(RESOURCES2_PROPERTY, propertyList);
+		addProperty(BODY_PROPERTY, propertyList);
+		addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
+		addProperty(FINALLY_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -109,15 +140,20 @@
 			case AST.JLS2_INTERNAL :
 			case AST.JLS3_INTERNAL :
 				return PROPERTY_DESCRIPTORS;
-			default :
+			case AST.JLS4_INTERNAL :
+			case AST.JLS8_INTERNAL :
 				return PROPERTY_DESCRIPTORS_4_0;
+			default :
+				return PROPERTY_DESCRIPTORS_9_0;
 		}
 	}
 
 	/**
-	 * The resource expressions (element type: {@link VariableDeclarationExpression}).
-	 * Null in JLS2 and JLS3. Added in JLS4; defaults to an empty list
-	 * (see constructor).
+	 * The resource expressions (element type: {@link Expression}).
+	 * Null in JLS2 and JLS3. Added in JLS4.
+	 * In the deprecated JLS4 and JLS8 APIs, this used to be
+	 * (element type: {@link VariableDeclarationExpression}).
+	 * Defaults to an empty list (see constructor).
 	 * @since 3.7
 	 */
 	private ASTNode.NodeList resources = null;
@@ -153,7 +189,9 @@
 	 */
 	TryStatement(AST ast) {
 		super(ast);
-		if (ast.apiLevel >= AST.JLS4_INTERNAL) {
+		if (ast.apiLevel >= AST.JLS9_INTERNAL) {
+			this.resources = new ASTNode.NodeList(RESOURCES2_PROPERTY);
+		} else if (ast.apiLevel >= AST.JLS4_INTERNAL) {
 			this.resources = new ASTNode.NodeList(RESOURCES_PROPERTY);
 		}
 	}
@@ -193,7 +231,7 @@
 	 * Method declared on ASTNode.
 	 */
 	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
-		if (property == RESOURCES_PROPERTY) {
+		if (property == RESOURCES_PROPERTY || property == RESOURCES2_PROPERTY) {
 			return resources();
 		}
 		if (property == CATCH_CLAUSES_PROPERTY) {
@@ -336,9 +374,12 @@
 
 	/**
 	 * Returns the live ordered list of resources for this try statement (added in JLS4 API).
+	 * 
+	 * <p>A resource is either a {@link VariableDeclarationExpression} or (since JLS9) a {@link Name}.</p>
 	 *
-	 * @return the live list of resources
-	 *    (element type: {@link VariableDeclarationExpression})
+	 * @return the live list of resources (element type: {@link Expression}).
+	 *    In the deprecated JLS4 and JLS8 APIs, this used to be
+	 *    (element type: {@link VariableDeclarationExpression}).
 	 * @exception UnsupportedOperationException if this operation is used
 	 *            in a JLS2 or JLS3 AST
 	 * @since 3.7.1
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
index 60e4f29..9b569e0 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeParameter.java
@@ -130,7 +130,7 @@
 	TypeParameter(AST ast) {
 		super(ast);
 	    unsupportedIn2();
-	    if (ast.apiLevel >= AST.JLS8) {
+	    if (ast.apiLevel >= AST.JLS8_INTERNAL) {
 			this.modifiers = new ASTNode.NodeList(MODIFIERS_PROPERTY);
 		}
 	}
@@ -185,7 +185,7 @@
 	ASTNode clone0(AST target) {
 		TypeParameter result = new TypeParameter(target);
 		result.setSourceRange(getStartPosition(), getLength());
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.modifiers().addAll(
 					ASTNode.copySubtrees(target, modifiers()));
 		}
@@ -210,7 +210,7 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.modifiers);
 			}
 			acceptChild(visitor, getName());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesStatement.java
new file mode 100644
index 0000000..75b0bc4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/UsesStatement.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Uses statement AST node type.
+ * <pre>
+ * UsesStatement:
+ *     <b>uses</b> Name <b>;</b>
+ * </pre>
+ *
+ * @since 3.13 BETA_JAVA9
+ * 
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@SuppressWarnings("rawtypes")
+public class UsesStatement extends ModuleStatement {
+
+	/**
+	 * The "type" structural property of this node type (child type: {@link Name}).
+	 */
+	public static final ChildPropertyDescriptor TYPE_PROPERTY =
+		new ChildPropertyDescriptor(UsesStatement.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS_9_0;
+
+	static {
+		List properyList = new ArrayList(2);
+		createPropertyList(UsesStatement.class, properyList);
+		addProperty(TYPE_PROPERTY, properyList);
+		PROPERTY_DESCRIPTORS_9_0 = reapPropertyList(properyList);
+	}
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		return PROPERTY_DESCRIPTORS_9_0;
+	}
+
+	/**
+	 * The module name; lazily initialized; defaults to a unspecified,
+	 * legal Java identifier.
+	 */
+	private Type type = null;
+
+	/**
+	 * Creates a new AST node for an uses statement owned by the
+	 * given AST. The uses statement initially is
+	 * for an unspecified, but legal, Java type name.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	UsesStatement(AST ast) {
+		super(ast);
+	}
+
+	@Override
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == TYPE_PROPERTY) {
+			if (get) {
+				return getType();
+			} else {
+				setType((Type) child);
+				return null;
+			}
+		}
+
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	@Override
+	final int getNodeType0() {
+		return USES_STATEMENT;
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		UsesStatement result = new UsesStatement(target);
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setType((Type) getType().clone(target));
+		return result;
+	}
+
+	@Override
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		if (visitChildren) {
+			acceptChild(visitor, getType());
+		}
+		visitor.endVisit(this);
+	}
+
+
+	/**
+	 * Returns the type in this statement
+	 *
+	 * @return the type
+	 */
+	public Type getType()  {
+		if (this.type == null) {
+			// lazy init must be thread-safe for readers
+			synchronized (this) {
+				if (this.type == null) {
+					preLazyInit();
+					this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+					postLazyInit(this.type, TYPE_PROPERTY);
+				}
+			}
+		}
+		return this.type;
+	}
+
+	/**
+	 * Sets the type in uses statement
+	 *
+	 * @param type the new type in uses
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */
+	public void setType(Type type) {
+		if (type == null) {
+			throw new IllegalArgumentException();
+		}
+		ASTNode oldChild = this.type;
+		preReplaceChild(oldChild, type, TYPE_PROPERTY);
+		this.type = type;
+		postReplaceChild(oldChild, type, TYPE_PROPERTY);
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 1 * 4;
+	}
+
+	@Override
+	int treeSize() {
+		return
+			memSize()
+			+ (this.type == null ? 0 : getType().treeSize());
+	}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
index 2a40ccb..3195f7e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclaration.java
@@ -196,7 +196,7 @@
 	 */
 	VariableDeclaration(AST ast) {
 		super(ast);
-		if (ast.apiLevel >= AST.JLS8) {
+		if (ast.apiLevel >= AST.JLS8_INTERNAL) {
 			this.extraDimensions = new ASTNode.NodeList(getExtraDimensions2Property());
 		}
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
index 0405c65..bd71410 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableDeclarationFragment.java
@@ -105,7 +105,7 @@
 	 * @since 3.0
 	 */
 	public static List propertyDescriptors(int apiLevel) {
-		if (apiLevel >= AST.JLS8) {
+		if (apiLevel >= AST.JLS8_INTERNAL) {
 			return PROPERTY_DESCRIPTORS_8_0;
 		} else {
 			return PROPERTY_DESCRIPTORS;
@@ -230,7 +230,7 @@
 		VariableDeclarationFragment result = new VariableDeclarationFragment(target);
 		result.setSourceRange(getStartPosition(), getLength());
 		result.setName((SimpleName) getName().clone(target));
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.extraDimensions().addAll(
 					ASTNode.copySubtrees(target, extraDimensions()));
 		} else {
@@ -257,7 +257,7 @@
 		if (visitChildren) {
 			// visit children in normal left to right reading order
 			acceptChild(visitor, getName());
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.extraDimensions);
 			}
 			acceptChild(visitor, getInitializer());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
index ab4572d..18ba40d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WildcardType.java
@@ -199,7 +199,7 @@
 	ASTNode clone0(AST target) {
 		WildcardType result = new WildcardType(target);
 		result.setSourceRange(getStartPosition(), getLength());
-		if (this.ast.apiLevel >= AST.JLS8) {
+		if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 			result.annotations().addAll(
 					ASTNode.copySubtrees(target, annotations()));
 		}
@@ -222,7 +222,7 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			// visit children in normal left to right reading order
-			if (this.ast.apiLevel >= AST.JLS8) {
+			if (this.ast.apiLevel >= AST.JLS8_INTERNAL) {
 				acceptChildren(visitor, this.annotations);
 			}
 			acceptChild(visitor, getBound());
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
index 503283c..52a6946 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
@@ -312,6 +312,9 @@
 	private static final char STATIC_PREFIX= 's';
 	private static final char NORMAL_PREFIX= 'n';
 
+	/** @deprecated using deprecated code */
+	private static final int JLS8_INTERNAL = AST.JLS8;
+
 	private final ImportRewriteContext defaultContext;
 
 	private final ICompilationUnit compilationUnit;
@@ -1308,7 +1311,7 @@
 
 		CompilationUnit usedAstRoot= this.astRoot;
 		if (usedAstRoot == null) {
-			ASTParser parser= ASTParser.newParser(AST.JLS8);
+			ASTParser parser= ASTParser.newParser(AST.JLS9);
 			parser.setSource(this.compilationUnit);
 			parser.setFocalPosition(0); // reduced AST
 			parser.setResolveBindings(false);
@@ -1325,7 +1328,7 @@
 			String qualifiedName = addedImport.substring(1);
 			computer.addImport(isStatic, qualifiedName);
 		}
-
+	
 		for (String removedImport : this.removedImports) {
 			boolean isStatic = STATIC_PREFIX == removedImport.charAt(0);
 			String qualifiedName = removedImport.substring(1);
@@ -1532,7 +1535,7 @@
 	private Type getArrayType(Type elementType, AST ast, ImportRewriteContext context, ITypeBinding normalizedBinding, TypeLocation location) {
 		int noDimensions = normalizedBinding.getDimensions();
 		ArrayType arrayType = ast.newArrayType(elementType, noDimensions);
-		if (ast.apiLevel() >= AST.JLS8) {
+		if (ast.apiLevel() >= JLS8_INTERNAL) {
 			for (int i = 0; i < noDimensions; i++) {
 				IAnnotationBinding[] typeAnnotations = normalizedBinding.getTypeAnnotations();
 				if (typeAnnotations.length > 0) {
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 2b079e4..1422c1b 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -64,6 +68,14 @@
 	private static final int JLS4 = AST.JLS4;
 
 	/**
+	 * Internal synonym for {@link AST#JLS8}. Use to alleviate
+	 * deprecation warnings.
+	 * @deprecated
+	 * @since 3.13 BETA_JAVA9
+	 */
+	private static final int JLS8 = AST.JLS8;
+	
+	/**
 	 * The string buffer into which the serialized representation of the AST is
 	 * written.
 	 */
@@ -199,11 +211,24 @@
 		}
 	}
 
+	private void printTypes(List<Type> types, String prefix) {
+		if (types.size() > 0) {
+			this.buffer.append(" " + prefix + " ");//$NON-NLS-1$ //$NON-NLS-2$
+			Type type = types.get(0);
+			type.accept(this);
+			for (int i = 1, l = types.size(); i < l; ++i) {
+				this.buffer.append(","); //$NON-NLS-1$
+				type = types.get(0);
+				type.accept(this);
+			}
+		}
+	}
+
 	/**
 	 * reference node helper function that is common to all
 	 * the difference reference nodes.
-	 * 
-	 * @param typeArguments list of type arguments 
+	 *
+	 * @param typeArguments list of type arguments
 	 */
 	private void visitReferenceTypeArguments(List typeArguments) {
 		this.buffer.append("::");//$NON-NLS-1$
@@ -221,7 +246,7 @@
 	}
 	
 	private void visitTypeAnnotations(AnnotatableType node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			visitAnnotationsList(node.annotations());
 		}
 	}
@@ -367,7 +392,7 @@
 	 * @see ASTVisitor#visit(ArrayType)
 	 */
 	public boolean visit(ArrayType node) {
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8) {
 			visitComponentType(node);
 			this.buffer.append("[]");//$NON-NLS-1$
 		} else {
@@ -736,9 +761,14 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ExportsStatement node) {
+		return visit(node, "exports"); //$NON-NLS-1$
+	}
+
 	/*
 	 * @see ASTVisitor#visit(ExpressionMethodReference)
-	 * 
+	 *
 	 * @since 3.10
 	 */
 	public boolean visit(ExpressionMethodReference node) {
@@ -1048,7 +1078,7 @@
 		}
 		node.getName().accept(this);
 		this.buffer.append("(");//$NON-NLS-1$
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			Type receiverType = node.getReceiverType();
 			if (receiverType != null) {
 				receiverType.accept(this);
@@ -1073,7 +1103,7 @@
 		}
 		this.buffer.append(")");//$NON-NLS-1$
 		int size = node.getExtraDimensions();
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			List dimensions = node.extraDimensions();
 			for (int i = 0; i < size; i++) {
 				visit((Dimension) dimensions.get(i));
@@ -1083,7 +1113,7 @@
 				this.buffer.append("[]"); //$NON-NLS-1$
 			}
 		}
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8) {
 			if (!thrownExceptions(node).isEmpty()) {
 				this.buffer.append(" throws ");//$NON-NLS-1$
 				for (Iterator it = thrownExceptions(node).iterator(); it.hasNext(); ) {
@@ -1199,6 +1229,35 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		if (node.getJavadoc() != null) {
+			node.getJavadoc().accept(this);
+		}
+		printModifiers(node.modifiers());
+		this.buffer.append("module"); //$NON-NLS-1$
+		this.buffer.append(" "); //$NON-NLS-1$
+		node.getName().accept(this);
+		this.buffer.append(" {\n"); //$NON-NLS-1$
+		this.indent++;
+		for (ModuleStatement stmt : (List<ModuleStatement>)node.moduleStatements()) {
+			stmt.accept(this);
+		}
+		this.indent--;
+		this.buffer.append("}"); //$NON-NLS-1$
+		return false;
+	}
+
+	private boolean visit(ModulePackageAccess node, String keyword) {
+		printIndent();
+		this.buffer.append(keyword);
+		this.buffer.append(" ");//$NON-NLS-1$
+		node.getName().accept(this);
+		printTypes(node.modules(), "to"); //$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(NameQualifiedType)
 	 * @since 3.10
@@ -1246,6 +1305,11 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(OpensStatement node) {
+		return visit(node, "opens"); //$NON-NLS-1$
+	}
+
 	/*
 	 * @see ASTVisitor#visit(PackageDeclaration)
 	 */
@@ -1322,6 +1386,17 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		printIndent();
+		this.buffer.append("provides");//$NON-NLS-1$
+		this.buffer.append(" ");//$NON-NLS-1$
+		node.getType().accept(this);
+		printTypes(node.implementations(), "with"); //$NON-NLS-1$
+		this.buffer.append(";\n");//$NON-NLS-1$
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(QualifiedName)
 	 */
@@ -1344,6 +1419,17 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(RequiresStatement node) {
+		printIndent();
+		this.buffer.append("requires");//$NON-NLS-1$
+		this.buffer.append(" ");//$NON-NLS-1$
+		printModifiers(node.modifiers());
+		node.getName().accept(this);
+		this.buffer.append(";\n");//$NON-NLS-1$
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(ReturnStatement)
 	 */
@@ -1402,7 +1488,7 @@
 		node.getType().accept(this);
 		if (node.getAST().apiLevel() >= JLS3) {
 			if (node.isVarargs()) {
-				if (node.getAST().apiLevel() >= AST.JLS8) {
+				if (node.getAST().apiLevel() >= JLS8) {
 					List annotations = node.varargsAnnotations();
 					if (annotations.size() > 0) {
 						this.buffer.append(' ');
@@ -1415,7 +1501,7 @@
 		this.buffer.append(" ");//$NON-NLS-1$
 		node.getName().accept(this);
 		int size = node.getExtraDimensions();
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			List dimensions = node.extraDimensions();
 			for (int i = 0; i < size; i++) {
 				visit((Dimension) dimensions.get(i));
@@ -1673,7 +1759,7 @@
 			if (!resources.isEmpty()) {
 				this.buffer.append('(');
 				for (Iterator it = resources.iterator(); it.hasNext(); ) {
-					VariableDeclarationExpression variable = (VariableDeclarationExpression) it.next();
+					Expression variable = (Expression) it.next();
 					variable.accept(this);
 					if (it.hasNext()) {
 						this.buffer.append(';');
@@ -1811,7 +1897,7 @@
 	 * @since 3.1
 	 */
 	public boolean visit(TypeParameter node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			printModifiers(node.modifiers());
 		}
 		node.getName().accept(this);
@@ -1843,6 +1929,16 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(UsesStatement node) {
+		printIndent();
+		this.buffer.append("uses");//$NON-NLS-1$
+		this.buffer.append(" ");//$NON-NLS-1$
+		node.getType().accept(this);
+		this.buffer.append(";\n");//$NON-NLS-1$
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(VariableDeclarationExpression)
 	 */
@@ -1871,7 +1967,7 @@
 	public boolean visit(VariableDeclarationFragment node) {
 		node.getName().accept(this);
 		int size = node.getExtraDimensions();
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8) {
 			List dimensions = node.extraDimensions();
 			for (int i = 0; i < size; i++) {
 				visit((Dimension) dimensions.get(i));
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 4f21b8e..f96ca35 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -113,6 +117,9 @@
 	private static final SimplePropertyDescriptor INTERNAL_VDS_MODIFIERS_PROPERTY = VariableDeclarationStatement.MODIFIERS_PROPERTY;
 
 	/** @deprecated using deprecated code */
+	private static final ChildListPropertyDescriptor INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY = TryStatement.RESOURCES_PROPERTY;
+
+	/** @deprecated using deprecated code */
 	private static final int JLS2_INTERNAL = AST.JLS2;
 	
 	/** @deprecated using deprecated code */
@@ -121,6 +128,11 @@
 	/** @deprecated using deprecated code */
 	private static final int JLS4_INTERNAL = AST.JLS4;
 
+	/** @deprecated using deprecated code */
+	private static final int JLS8_INTERNAL = AST.JLS8;
+
+	private static final int JLS9_INTERNAL = AST.JLS9;
+
 
 	TextEdit currentEdit;
 	final RewriteEventStore eventStore; // used from inner classes
@@ -1318,13 +1330,10 @@
 		}
 	}
 
-	/*
-	 * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset.
-	 */
-	private int getPosAfterLeftBrace(int pos) {
+	private int getPosAfterToken(int pos, int token) {
 		try {
 			int nextToken= getScanner().readNext(pos, true);
-			if (nextToken == TerminalTokens.TokenNameLBRACE) {
+			if (nextToken == token) {
 				return getScanner().getCurrentEndOffset();
 			}
 		} catch (CoreException e) {
@@ -1332,6 +1341,12 @@
 		}
 		return pos;
 	}
+	/*
+	 * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset.
+	 */
+	private int getPosAfterLeftBrace(int pos) {
+		return getPosAfterToken(pos, TerminalTokens.TokenNameLBRACE);
+	}
 
 	/*
 	 * Next token is try keyword. Returns the offset after 'try' keyword. For incomplete code, return the start offset.
@@ -1682,6 +1697,10 @@
 			return doVisitUnchangedChildren(node);
 		}
 
+		if (node.getAST().apiLevel() >= JLS9_INTERNAL && node.getModule() != null) {
+			rewriteNode(node, CompilationUnit.MODULE_PROPERTY, 0, ASTRewriteFormatter.NONE);
+			return false;
+		}
 		int startPos= rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE);
 
 		if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) {
@@ -1851,7 +1870,7 @@
 	
 	private int rewriteMethodReceiver(MethodDeclaration method, int offset) throws CoreException {
 		offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLPAREN, offset);
-		if (method.getAST().apiLevel() < AST.JLS8) {
+		if (method.getAST().apiLevel() < JLS8_INTERNAL) {
 			return offset;
 		}
 
@@ -2034,9 +2053,9 @@
 			pos= rewriteNodeList(node, MethodDeclaration.PARAMETERS_PROPERTY, pos, Util.EMPTY_STRING, ", "); //$NON-NLS-1$ 
 
 			pos= getScanner().getTokenEndOffset(TerminalTokens.TokenNameRPAREN, pos);
-			ChildListPropertyDescriptor exceptionsProperty = apiLevel < AST.JLS8 ? INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY;
+			ChildListPropertyDescriptor exceptionsProperty = apiLevel < JLS8_INTERNAL ? INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY;
 
-			if (apiLevel < AST.JLS8) {
+			if (apiLevel < JLS8_INTERNAL) {
 				int extraDims= rewriteExtraDimensions(node, INTERNAL_METHOD_EXTRA_DIMENSIONS_PROPERTY, pos);
 
 				boolean hasExceptionChanges= isChanged(node, exceptionsProperty);
@@ -2063,6 +2082,22 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos= rewriteJavadoc(node, ModuleDeclaration.JAVADOC_PROPERTY);
+		pos= rewriteModifiers2(node, ModuleDeclaration.MODIFIERS_PROPERTY, pos);
+		pos= rewriteRequiredNode(node, ModuleDeclaration.NAME_PROPERTY);
+		int startPos = getPosAfterLeftBrace(pos);
+		int startIndent= getIndent(node.getStartPosition()) + 1;
+		this.tokenScanner.getScanner().fakeInModule = true;
+		rewriteParagraphList(node, ModuleDeclaration.MODULE_STATEMENTS_PROPERTY, startPos, startIndent, 0, 1);
+		this.tokenScanner.getScanner().fakeInModule = false;
+		return false;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Block)
 	 */
@@ -2102,6 +2137,15 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(RequiresStatement node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteModifiers2(node, RequiresStatement.MODIFIERS_PROPERTY, getPosAfterToken(node.getStartPosition(), TerminalTokens.TokenNamerequires));
+		rewriteRequiredNode(node, RequiresStatement.NAME_PROPERTY);
+		return false;
+	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AnonymousClassDeclaration)
@@ -2141,7 +2185,7 @@
 		ArrayType arrayType= (ArrayType) getOriginalValue(node, ArrayCreation.TYPE_PROPERTY);
 		ArrayType replacingType= arrayType;
 		int nOldBrackets= getDimensions(arrayType); // number of total brackets
-		boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8;
+		boolean astLevelGTE8 = node.getAST().apiLevel() >= JLS8_INTERNAL;
 		boolean typeReplaced = false;
 
 		TextEditGroup editGroup= null;
@@ -2314,7 +2358,7 @@
 	}
 
 	private Type getElementType(ArrayType parent) {
-		if (parent.getAST().apiLevel() >= AST.JLS8) {
+		if (parent.getAST().apiLevel() >= JLS8_INTERNAL) {
 			return (Type) getOriginalValue(parent, ArrayType.ELEMENT_TYPE_PROPERTY);
 		}
 		Type t = (Type) getOriginalValue(parent, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY);
@@ -2325,7 +2369,7 @@
 	}
 
 	private int getDimensions(ArrayType parent) {
-		if (parent.getAST().apiLevel() >= AST.JLS8) {
+		if (parent.getAST().apiLevel() >= JLS8_INTERNAL) {
 			return ((List) getOriginalValue(parent, ArrayType.DIMENSIONS_PROPERTY)).size();
 		}
 		Type t = (Type) getOriginalValue(parent, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY);
@@ -2361,7 +2405,7 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8_INTERNAL) {
 			rewriteRequiredNode(node, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY);
 		} else {
 			int pos = rewriteRequiredNode(node, ArrayType.ELEMENT_TYPE_PROPERTY);
@@ -2640,6 +2684,16 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ExportsStatement node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos = rewriteRequiredNode(node, ExportsStatement.NAME_PROPERTY);
+		rewriteNodeList(node, ExportsStatement.MODULES_PROPERTY, pos, "to ", ", "); //$NON-NLS-1$ //$NON-NLS-2$ 
+
+		return false;
+	}
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ExpressionStatement)
 	 */
@@ -3204,7 +3258,7 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			rewriteTypeAnnotations(node, PrimitiveType.ANNOTATIONS_PROPERTY, node.getStartPosition());
 		}
 		PrimitiveType.Code newCode= (PrimitiveType.Code) getNewValue(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY);
@@ -3213,6 +3267,15 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		int pos = rewriteRequiredNode(node, ProvidesStatement.TYPE_PROPERTY);
+		pos= rewriteNodeList(node, ProvidesStatement.IMPLEMENTATIONS_PROPERTY, pos, " with ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
+		return false;
+	}
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(QualifiedName)
 	 */
@@ -3246,7 +3309,7 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			rewriteTypeAnnotations(node, SimpleType.ANNOTATIONS_PROPERTY, node.getStartPosition());
 		}
 		rewriteRequiredNode(node, SimpleType.NAME_PROPERTY);
@@ -3272,7 +3335,7 @@
 			if (isChanged(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
 				TextEditGroup editGroup = getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY);
 				if (getNewValue(node, SingleVariableDeclaration.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
-					if (apiLevel >= AST.JLS8) {
+					if (apiLevel >= JLS8_INTERNAL) {
 						pos= rewriteVarargsAnnotations(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, pos);
 					}
 					int indent= getIndent(node.getStartPosition());
@@ -3282,7 +3345,7 @@
 				} else {
 					try {
 						int ellipsisEnd;
-						int noOfAnnotations = apiLevel >= AST.JLS8 ? node.varargsAnnotations().size() : 0;
+						int noOfAnnotations = apiLevel >= JLS8_INTERNAL ? node.varargsAnnotations().size() : 0;
 						if (noOfAnnotations > 0) {
 							Annotation annotation= (Annotation) node.varargsAnnotations().get(noOfAnnotations - 1);
 							int annotationEndPosition= annotation.getStartPosition() + annotation.getLength();
@@ -3296,7 +3359,7 @@
 					}
 				}
 			} else {
-				if (apiLevel >= AST.JLS8 && node.isVarargs()) {
+				if (apiLevel >= JLS8_INTERNAL && node.isVarargs()) {
 					pos = rewriteVarargsAnnotations(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, pos);
 				}
 			}
@@ -3308,7 +3371,7 @@
 		}
 
 		pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY);
-		if (apiLevel < AST.JLS8) {
+		if (apiLevel < JLS8_INTERNAL) {
 			int extraDims= rewriteExtraDimensions(node, INTERNAL_VARIABLE_EXTRA_DIMENSIONS_PROPERTY, pos);
 
 			if (extraDims > 0) {
@@ -3613,14 +3676,16 @@
 			return doVisitUnchangedChildren(node);
 		}
 		int pos= node.getStartPosition();
-		if (node.getAST().apiLevel() >= JLS4_INTERNAL) {
-			if (isChanged(node, TryStatement.RESOURCES_PROPERTY)) {
+		int level = node.getAST().apiLevel();
+		if (level >= JLS4_INTERNAL) {
+			StructuralPropertyDescriptor desc = level < JLS9_INTERNAL ? INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY : TryStatement.RESOURCES2_PROPERTY;
+			if (isChanged(node, desc)) {
 				int indent= getIndent(node.getStartPosition());
 				String prefix= this.formatter.TRY_RESOURCES.getPrefix(indent);
 				String newParen = this.formatter.TRY_RESOURCES_PAREN.getPrefix(indent) + "("; //$NON-NLS-1$
-				pos= rewriteNodeList(node, TryStatement.RESOURCES_PROPERTY, getPosAfterTry(pos), newParen, ")", ";" + prefix); //$NON-NLS-1$ //$NON-NLS-2$
+				pos= rewriteNodeList(node, desc, getPosAfterTry(pos), newParen, ")", ";" + prefix); //$NON-NLS-1$ //$NON-NLS-2$
 			} else {
-				pos= doVisit(node, TryStatement.RESOURCES_PROPERTY, pos);
+				pos= doVisit(node, desc, pos);
 			}
 		}
 
@@ -3676,7 +3741,16 @@
 		rewriteNodeList(node, UnionType.TYPES_PROPERTY, node.getStartPosition(), Util.EMPTY_STRING, " | "); //$NON-NLS-1$
 		return false;
 	}
-	
+
+	@Override
+	public boolean visit(UsesStatement node) {
+		if (!hasChildrenChanges(node)) {
+			return doVisitUnchangedChildren(node);
+		}
+		rewriteRequiredNode(node,UsesStatement.TYPE_PROPERTY);
+		return false;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationExpression)
 	 */
@@ -3707,7 +3781,7 @@
 
 		int pos= rewriteRequiredNode(node, VariableDeclarationFragment.NAME_PROPERTY);
 
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8_INTERNAL) {
 			int extraDims= rewriteExtraDimensions(node, INTERNAL_FRAGMENT_EXTRA_DIMENSIONS_PROPERTY, pos);
 			if (extraDims > 0) {
 				int kind= getChangeKind(node, VariableDeclarationFragment.INITIALIZER_PROPERTY);
@@ -4210,7 +4284,7 @@
 			return doVisitUnchangedChildren(node);
 		}
 		int pos = rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY);
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			try {
 				pos = getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos);
 				rewriteTypeAnnotations(node, QualifiedType.ANNOTATIONS_PROPERTY, pos);
@@ -4267,7 +4341,7 @@
 			return doVisitUnchangedChildren(node);
 		}
 		int pos;
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			pos = rewriteModifiers2(node, TypeParameter.MODIFIERS_PROPERTY, node.getStartPosition());
 		}
 		pos= rewriteRequiredNode(node, TypeParameter.NAME_PROPERTY);
@@ -4281,7 +4355,7 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			rewriteTypeAnnotations(node, WildcardType.ANNOTATIONS_PROPERTY, node.getStartPosition());
 		}
 		try {
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 33a4b20..6850a42 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -70,6 +74,9 @@
 	private static final SimplePropertyDescriptor INTERNAL_VDS_MODIFIERS_PROPERTY = VariableDeclarationStatement.MODIFIERS_PROPERTY;
 
 	/** @deprecated using deprecated code */
+	private static final ChildListPropertyDescriptor INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY = TryStatement.RESOURCES_PROPERTY;
+
+	/** @deprecated using deprecated code */
 	private static final int JLS2_INTERNAL = AST.JLS2;
 
 	/** @deprecated using deprecated code */
@@ -78,6 +85,11 @@
 	/** @deprecated using deprecated code */
 	private static final int JLS4_INTERNAL = AST.JLS4;
 
+	/** @deprecated using deprecated code */
+	private static final int JLS8_INTERNAL = AST.JLS8;
+
+	private static final int JLS9_INTERNAL = AST.JLS9;
+
 
 	public static String asString(ASTNode node, RewriteEventStore store) {
 		ASTRewriteFlattener flattener= new ASTRewriteFlattener(store);
@@ -197,7 +209,7 @@
 	}
 
 	private void visitExtraDimensions(ASTNode node, SimplePropertyDescriptor dimensions, ChildListPropertyDescriptor dimensionsInfo) {
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8_INTERNAL) {
 			int extraDimensions= getIntAttribute(node, dimensions);
 			for (int i = 0; i < extraDimensions; i++) {
 				this.result.append("[]"); //$NON-NLS-1$
@@ -238,7 +250,7 @@
 		// get the element type and count dimensions
 		Type elementType;
 		int dimensions;
-		boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8;
+		boolean astLevelGTE8 = node.getAST().apiLevel() >= JLS8_INTERNAL;
 		if (astLevelGTE8) {
 			elementType = (Type) getChildNode(arrayType, ArrayType.ELEMENT_TYPE_PROPERTY);
 			dimensions = getChildList(arrayType, ArrayType.DIMENSIONS_PROPERTY).size();
@@ -297,7 +309,7 @@
 	 * @see ASTVisitor#visit(ArrayType)
 	 */
 	public boolean visit(ArrayType node) {
-		if (node.getAST().apiLevel() < AST.JLS8) {
+		if (node.getAST().apiLevel() < JLS8_INTERNAL) {
 			getChildNode(node, INTERNAL_ARRAY_COMPONENT_TYPE_PROPERTY).accept(this);
 			this.result.append("[]"); //$NON-NLS-1$
 		} else {
@@ -428,10 +440,13 @@
 		return false;
 	}
 
-	/*
-	 * @see ASTVisitor#visit(CompilationUnit)
-	 */
+	@Override
 	public boolean visit(CompilationUnit node) {
+		ASTNode module= getChildNode(node, CompilationUnit.MODULE_PROPERTY);
+		if (module != null) {
+			module.accept(this);
+		}
+
 		ASTNode pack= getChildNode(node, CompilationUnit.PACKAGE_PROPERTY);
 		if (pack != null) {
 			pack.accept(this);
@@ -517,6 +532,19 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ExportsStatement node) {
+		this.result.append("exports "); //$NON-NLS-1$
+		getChildNode(node, ExportsStatement.NAME_PROPERTY).accept(this);
+		List<Name> modules = node.modules();
+		if (modules.size() > 0) {
+			this.result.append(" to "); //$NON-NLS-1$
+			visitList(node, ExportsStatement.MODULES_PROPERTY, Util.COMMA_SEPARATOR, Util.EMPTY_STRING, Util.EMPTY_STRING);
+		}
+		this.result.append(';');
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(ExpressionStatement)
 	 */
@@ -737,7 +765,7 @@
 		getChildNode(node, MethodDeclaration.NAME_PROPERTY).accept(this);
 		this.result.append('(');
 		// receiver parameter
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			ASTNode receiverType = getChildNode(node, MethodDeclaration.RECEIVER_TYPE_PROPERTY);
 			if (receiverType != null) {
 				receiverType.accept(this);
@@ -758,7 +786,7 @@
 		this.result.append(')');
 		visitExtraDimensions(node, INTERNAL_METHOD_EXTRA_DIMENSIONS_PROPERTY, MethodDeclaration.EXTRA_DIMENSIONS2_PROPERTY);
 
-		ChildListPropertyDescriptor exceptionsProperty = node.getAST().apiLevel() <	AST.JLS8 ? 
+		ChildListPropertyDescriptor exceptionsProperty = node.getAST().apiLevel() <	JLS8_INTERNAL ? 
 				INTERNAL_METHOD_THROWN_EXCEPTIONS_PROPERTY : MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY;
 		visitList(node, exceptionsProperty, String.valueOf(','), " throws ", Util.EMPTY_STRING); //$NON-NLS-1$			
 		ASTNode body= getChildNode(node, MethodDeclaration.BODY_PROPERTY);
@@ -770,6 +798,21 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		ASTNode javadoc= getChildNode(node, ModuleDeclaration.JAVADOC_PROPERTY);
+		if (javadoc != null) {
+			javadoc.accept(this);
+		}
+		visitList(node, ModuleDeclaration.MODIFIERS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+		this.result.append("module "); //$NON-NLS-1$
+		getChildNode(node, ModuleDeclaration.NAME_PROPERTY).accept(this);
+		this.result.append('{');
+		visitList(node, ModuleDeclaration.MODULE_STATEMENTS_PROPERTY, null);
+		this.result.append('}');
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(MethodInvocation)
 	 */
@@ -851,11 +894,21 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		this.result.append("provides "); //$NON-NLS-1$
+		getChildNode(node, ProvidesStatement.TYPE_PROPERTY).accept(this);
+		this.result.append(" with "); //$NON-NLS-1$
+		visitList(node, ProvidesStatement.IMPLEMENTATIONS_PROPERTY, Util.EMPTY_STRING, Util.COMMA_SEPARATOR, Util.EMPTY_STRING);
+		this.result.append(';');
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(PrimitiveType)
 	 */
 	public boolean visit(PrimitiveType node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, PrimitiveType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		this.result.append(getAttribute(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY).toString());
@@ -872,6 +925,15 @@
 		return false;
 	}
 
+	@Override
+	public boolean visit(RequiresStatement node) {
+		this.result.append("requires "); //$NON-NLS-1$
+		visitList(node, RequiresStatement.MODIFIERS_PROPERTY, Util.EMPTY_STRING, Util.EMPTY_STRING, String.valueOf(' '));
+		getChildNode(node, RequiresStatement.NAME_PROPERTY).accept(this);
+		this.result.append(';');
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(ReturnStatement)
 	 */
@@ -898,7 +960,7 @@
 	 * @see ASTVisitor#visit(SimpleType)
 	 */
 	public boolean visit(SimpleType node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, SimpleType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		node.getName().accept(this);
@@ -915,7 +977,7 @@
 			visitList(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		getChildNode(node, SingleVariableDeclaration.TYPE_PROPERTY).accept(this);
-		if (node.getAST().apiLevel() >= AST.JLS8  && node.isVarargs()) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL  && node.isVarargs()) {
 			visitList(node, SingleVariableDeclaration.VARARGS_ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		if (node.getAST().apiLevel() >= JLS3_INTERNAL) {
@@ -1061,8 +1123,10 @@
 	 */
 	public boolean visit(TryStatement node) {
 		this.result.append("try "); //$NON-NLS-1$
-		if (node.getAST().apiLevel() >= JLS4_INTERNAL) {
-			visitList(node, TryStatement.RESOURCES_PROPERTY, String.valueOf(';'), String.valueOf('('), String.valueOf(')'));
+		int level = node.getAST().apiLevel();
+		if (level >= JLS4_INTERNAL) {
+			StructuralPropertyDescriptor desc = level < JLS9_INTERNAL ? INTERNAL_TRY_STATEMENT_RESOURCES_PROPERTY : TryStatement.RESOURCES2_PROPERTY;
+			visitList(node, desc, String.valueOf(';'), String.valueOf('('), String.valueOf(')'));
 		}
 		getChildNode(node, TryStatement.BODY_PROPERTY).accept(this);
 		this.result.append(' ');
@@ -1147,6 +1211,14 @@
 		return false;
 	}
 	
+	@Override
+	public boolean visit(UsesStatement node) {
+		this.result.append("uses "); //$NON-NLS-1$
+		getChildNode(node, UsesStatement.TYPE_PROPERTY).accept(this);
+		this.result.append(';');
+		return false;
+	}
+
 	/*
 	 * @see ASTVisitor#visit(VariableDeclarationExpression)
 	 */
@@ -1446,7 +1518,7 @@
 	public boolean visit(NameQualifiedType node) {
 		getChildNode(node, NameQualifiedType.QUALIFIER_PROPERTY).accept(this);
 		this.result.append('.');
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, NameQualifiedType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		getChildNode(node, NameQualifiedType.NAME_PROPERTY).accept(this);
@@ -1472,7 +1544,7 @@
 	public boolean visit(QualifiedType node) {
 		getChildNode(node, QualifiedType.QUALIFIER_PROPERTY).accept(this);
 		this.result.append('.');
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, QualifiedType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		getChildNode(node, QualifiedType.NAME_PROPERTY).accept(this);
@@ -1521,7 +1593,7 @@
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
 	 */
 	public boolean visit(TypeParameter node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, TypeParameter.MODIFIERS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		getChildNode(node, TypeParameter.NAME_PROPERTY).accept(this);
@@ -1533,7 +1605,7 @@
 	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
 	 */
 	public boolean visit(WildcardType node) {
-		if (node.getAST().apiLevel() >= AST.JLS8) {
+		if (node.getAST().apiLevel() >= JLS8_INTERNAL) {
 			visitList(node, WildcardType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
 		}
 		this.result.append('?');
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
index 24b0b5e..23523bf 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEnvironment.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
index 20c5ed9..23fdfc5 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller <jesper@selskabet.org> - Contributions for
@@ -449,7 +453,7 @@
 		PackageBinding packageBinding = (PackageBinding) binding;
 
 		while (currentIndex < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], null);
 			invocationSite.setFieldIndex(currentIndex);
  			if (binding == null) {
 	 			if (currentIndex == length) // must be a type if its the last name, otherwise we have no idea if its a package or type
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
index b95eccd..b7c0b2e 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -199,6 +203,11 @@
 	return walker;
 }
 @Override
+public char[] getModule() {
+	// TODO BETA_JAVA9 Auto-generated method stub
+	return null;
+}
+@Override
 public ExternalAnnotationStatus getExternalAnnotationStatus() {
 	return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
index c8391d0..1fdfb58 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
@@ -321,6 +321,10 @@
 		public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selectorEnd, char[] typeParameterName,boolean isDeclaration, int start, int end) {
 			originalRequestor.acceptMethodTypeParameter(declaringTypePackageName, declaringTypeName, selector, selectorStart, selectorEnd, typeParameterName, isDeclaration, start, end);
 		}
+		@Override
+		public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) {
+			originalRequestor.acceptModule(moduleName, uniqueKey, start, end);
+		}
 	};
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
index b38d05b..3c60376 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -160,6 +164,11 @@
 		public boolean ignoreOptionalProblems() {
 			return false;
 		}
+		@Override
+		public char[] module() {
+			// TODO BETA_JAVA9 Auto-generated method stub
+			return null;
+		}
 	};
 
 	CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project, owner, monitor);
@@ -607,6 +616,10 @@
 		public boolean ignoreOptionalProblems() {
 			return false;
 		}
+		@Override
+		public char[] module() {
+			return null;
+		}
 	};
 	SelectionEngine engine = new SelectionEngine(environment, mapper.getSelectionRequestor(requestor), options, owner);
 	engine.select(sourceUnit, mapper.startPosOffset + selectionSourceStart, mapper.startPosOffset + selectionSourceEnd);
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
index fe2da22..ed861f5 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -145,6 +149,11 @@
 		public boolean ignoreOptionalProblems() {
 			return false;
 		}
+		@Override
+		public char[] module() {
+			// TODO BETA_JAVA9 Auto-generated method stub
+			return null;
+		}
 	}});
 	if (compilerRequestor.hasErrors) {
 		return null;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java
index 75a8ff9..4b46f88 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -109,6 +109,17 @@
 	public static final int K_JAVA_DOC = 0x40;
 
 	/**
+	 * Kind used to format a module description (a module-info.java file).
+	 * <p>
+	 * If the corresponding comment option is set to <code>true</code> then it is
+	 * also possible to format the comments on the fly by adding the
+	 * {@link #F_INCLUDE_COMMENTS} flag to this kind of format.
+	 * </p>
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int K_MODULE_INFO = 0x80;
+
+	/**
 	 * Flag used to include the comments during the formatting of the code
 	 * snippet.
 	 * <p>
@@ -119,6 +130,7 @@
 	 * 		<li>{@link #K_CLASS_BODY_DECLARATIONS} <i>(since 3.6)</i></li>
 	 * 		<li>{@link #K_EXPRESSION} <i>(since 3.6)</i></li>
 	 * 		<li>{@link #K_STATEMENTS} <i>(since 3.6)</i></li>
+	 * 		<li>{@link #K_MODULE_INFO}</li>
 	 * </ul>
 	 * </p><p>
 	 * Note also that it has an effect only when one or several format comments
@@ -201,7 +213,8 @@
 	 * 	<li>{@link #K_EXPRESSION}</li>
 	 * 	<li>{@link #K_STATEMENTS}</li>
 	 * 	<li>{@link #K_CLASS_BODY_DECLARATIONS}</li>
-	 * 	<li>{@link #K_COMPILATION_UNIT}<br>
+	 * 	<li>{@link #K_COMPILATION_UNIT}</li>
+	 * 	<li>{@link #K_MODULE_INFO}<br>
 	 * 		<b>Since 3.4</b>, the comments can be formatted on the fly while
 	 * 		using this kind of code snippet<br>
 	 * 		(see {@link #F_INCLUDE_COMMENTS} for more detailed explanation on
@@ -244,7 +257,8 @@
 	 * 	<li>{@link #K_EXPRESSION}</li>
 	 * 	<li>{@link #K_STATEMENTS}</li>
 	 * 	<li>{@link #K_CLASS_BODY_DECLARATIONS}</li>
-	 * 	<li>{@link #K_COMPILATION_UNIT}<br>
+	 * 	<li>{@link #K_COMPILATION_UNIT}</li>
+	 * 	<li>{@link #K_MODULE_INFO}<br>
 	 * 		<b>Since 3.4</b>, the comments can be formatted on the fly while
 	 * 		using this kind of code snippet<br>
 	 * 		(see {@link #F_INCLUDE_COMMENTS} for more detailed explanation on
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index e182aea..0d782c1 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -236,6 +236,17 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_method_declaration";	 //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of module statements
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_module_statements"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_module_statements";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of multiple fields
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_multiple_fields"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
index 8200ee8..b196404 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
@@ -60,10 +60,10 @@
 		String breakBeforeTags = "(dd|dt|li|td|th|h1|h2|h3|h4|h5|h6|q)"; //$NON-NLS-1$
 		String breakAfterTags = "(br)"; //$NON-NLS-1$
 		String noFormatTags = "(code|tt)"; //$NON-NLS-1$
-		String otherTags = "([^<>&&\\S]++)"; //$NON-NLS-1$
+		String otherTags = "([\\S&&[^<>]]++)"; //$NON-NLS-1$
 		String ws = "(?>[ \\t]++|[\\r\\n]++[ \\t]*+\\*?)"; // whitespace or line break with optional asterisk //$NON-NLS-1$
-		String attributeValue = "(?>\"[^\"]*\")|(?>\'[^\']*\')|[^/>\"\'&&\\S]++"; //$NON-NLS-1$
-		String attribute = "(?>" + ws + "+[^=&&\\S]+" + ws + "*(=)" + ws + "*(?>" + attributeValue  + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+		String attributeValue = "(?>\"[^\"]*\")|(?>\'[^\']*\')|[\\S&&[^/>\"\']]++"; //$NON-NLS-1$
+		String attribute = "(?>" + ws + "+[\\S&&[^=]]+" + ws + "*(=)" + ws + "*(?>" + attributeValue  + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
 		HTML_TAG_PATTERN = Pattern.compile("<(/)?+(?:" //$NON-NLS-1$
 				+ formatCodeTags + '|' + separateLineTags + '|' + breakBeforeTags + '|' + breakAfterTags + '|' + noFormatTags + '|' + otherTags + ')'
 				+ "(" + attribute + "*)" + ws + "*/?>", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
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 e469e88..683d70d 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,10 +24,15 @@
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -41,8 +46,10 @@
 import org.eclipse.jdt.core.formatter.CodeFormatter;
 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.PackageFragment;
 import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor;
 import org.eclipse.jdt.internal.formatter.linewrap.WrapPreparator;
 import org.eclipse.jface.text.IRegion;
@@ -67,8 +74,18 @@
 		| K_STATEMENTS
 		| K_CLASS_BODY_DECLARATIONS
 		| K_COMPILATION_UNIT
+		| K_MODULE_INFO
 		| K_COMMENTS_MASK;
 
+	private static final Map<Integer, Integer> FORMAT_TO_PARSER_KIND = new HashMap<>();
+	static {
+		FORMAT_TO_PARSER_KIND.put(K_COMPILATION_UNIT, ASTParser.K_COMPILATION_UNIT);
+		FORMAT_TO_PARSER_KIND.put(K_MODULE_INFO, ASTParser.K_COMPILATION_UNIT);
+		FORMAT_TO_PARSER_KIND.put(K_CLASS_BODY_DECLARATIONS, ASTParser.K_CLASS_BODY_DECLARATIONS);
+		FORMAT_TO_PARSER_KIND.put(K_STATEMENTS, ASTParser.K_STATEMENTS);
+		FORMAT_TO_PARSER_KIND.put(K_EXPRESSION, ASTParser.K_EXPRESSION);
+	}
+
 	private DefaultCodeFormatterOptions originalOptions;
 	private DefaultCodeFormatterOptions workingOptions;
 
@@ -76,7 +93,7 @@
 	private String sourceLevel;
 
 	private String sourceString;
-	private char[] sourceArray;
+	char[] sourceArray;
 	private List<IRegion> formatRegions;
 
 	private ASTNode astRoot;
@@ -170,7 +187,7 @@
 		return result;
 	}
 
-	private boolean init(String source) {
+	private boolean init(String source, int kind) {
 
 		// this is convenient for debugging (see Token.toString())
 		// Token.source = source;
@@ -180,7 +197,7 @@
 		this.tokens.clear();
 		this.tokenManager = new TokenManager(this.tokens, source, this.workingOptions);
 
-		tokenizeSource();
+		tokenizeSource(kind);
 		return !this.tokens.isEmpty();
 	}
 
@@ -190,7 +207,7 @@
 	}
 
 	private List<Token> prepareFormattedCode(String source, int kind) {
-		if (!init(source))
+		if (!init(source, kind))
 			return null;
 
 		this.astRoot = parseSourceCode(kind);
@@ -222,7 +239,7 @@
 
 	private TextEdit formatComments(String source, int kind) {
 		MultiTextEdit result = new MultiTextEdit();
-		if (!init(source))
+		if (!init(source, kind))
 			return result;
 
 		CommentsPreparator commentsPreparator = new CommentsPreparator(this.tokenManager, this.workingOptions,
@@ -230,12 +247,9 @@
 		CommentWrapExecutor commentWrapper = new CommentWrapExecutor(this.tokenManager, this.workingOptions);
 		switch (kind) {
 			case K_JAVA_DOC:
-				ASTParser parser = ASTParser.newParser(AST.JLS8);
 				for (Token token : this.tokens) {
 					if (token.tokenType == TokenNameCOMMENT_JAVADOC) {
-						parser.setSourceRange(token.originalStart, token.countChars());
-						CompilationUnit cu = (CompilationUnit) parseSourceCode(parser, ASTParser.K_COMPILATION_UNIT,
-								true);
+						CompilationUnit cu = (CompilationUnit) parseSourceCode(ASTParser.K_COMPILATION_UNIT);
 						Javadoc javadoc = (Javadoc) cu.getCommentList().get(0);
 						javadoc.accept(commentsPreparator);
 						int startPosition = this.tokenManager.findSourcePositionInLine(token.originalStart);
@@ -290,59 +304,67 @@
 	}
 
 	private ASTNode parseSourceCode(int kind) {
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		kind = kind & K_MASK;
+		if (kind != K_UNKNOWN) {
+			ASTNode astNode = createParser(kind).createAST(null);
+			if (kind == K_COMPILATION_UNIT || kind == K_MODULE_INFO)
+				return astNode;
+			return hasErrors(astNode) ? null : astNode;
+		}
+
+		int[] kindsToTry = { K_COMPILATION_UNIT, K_EXPRESSION, K_CLASS_BODY_DECLARATIONS, K_STATEMENTS, K_MODULE_INFO };
+		for (int kindToTry : kindsToTry) {
+			ASTNode astNode = createParser(kindToTry).createAST(null);
+			if (!hasErrors(astNode)) {
+				if (kindToTry == K_MODULE_INFO) 
+					tokenizeSource(kindToTry); // run scanner again to get module specific tokens
+				return astNode;
+			}
+		}
+		return null;
+	}
+
+	private ASTParser createParser(int kind) {
+		ASTParser parser = ASTParser.newParser(AST.JLS9);
+
+		if (kind == K_MODULE_INFO) {
+			Path fakeModuleInfoPath = new Path("project/" + TypeConstants.MODULE_INFO_FILE_NAME_STRING); //$NON-NLS-1$
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(fakeModuleInfoPath);
+			ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
+			parser.setSource(new org.eclipse.jdt.internal.core.CompilationUnit((PackageFragment) unit.getParent(),
+					unit.getElementName(), unit.getOwner()) {
+				@Override
+				public char[] getContents() {
+					return DefaultCodeFormatter.this.sourceArray;
+				}
+			});
+		} else {
+			parser.setSource(this.sourceArray);
+		}
+		parser.setKind(FORMAT_TO_PARSER_KIND.get(kind));
+
 		Map<String, String> parserOptions = JavaCore.getOptions();
 		parserOptions.put(CompilerOptions.OPTION_Source, this.sourceLevel);
 		parserOptions.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
 		parser.setCompilerOptions(parserOptions);
-
-		switch (kind & K_MASK) {
-			case K_COMPILATION_UNIT:
-				return parseSourceCode(parser, ASTParser.K_COMPILATION_UNIT, true);
-			case K_CLASS_BODY_DECLARATIONS:
-				return parseSourceCode(parser, ASTParser.K_CLASS_BODY_DECLARATIONS, false);
-			case K_STATEMENTS:
-				return parseSourceCode(parser, ASTParser.K_STATEMENTS, false);
-			case K_EXPRESSION:
-				return parseSourceCode(parser, ASTParser.K_EXPRESSION, false);
-			case K_UNKNOWN:
-				int[] parserModes = { ASTParser.K_COMPILATION_UNIT, ASTParser.K_EXPRESSION,
-						ASTParser.K_CLASS_BODY_DECLARATIONS, ASTParser.K_STATEMENTS };
-				for (int parserMode : parserModes) {
-					ASTNode astNode = parseSourceCode(parser, parserMode, false);
-					if (astNode != null)
-						return astNode;
-					parser.setCompilerOptions(parserOptions); // parser loses compiler options after every use
-				}
-				return null;
-			default:
-				throw new IllegalArgumentException();
-		}
+		return parser;
 	}
 
-	private ASTNode parseSourceCode(ASTParser parser, int parserMode, boolean ignoreErrors) {
-		parser.setKind(parserMode);
-		parser.setSource(this.sourceArray);
-		ASTNode astNode = parser.createAST(null);
-		if (ignoreErrors)
-			return astNode;
-
-		boolean hasErrors = false;
+	private boolean hasErrors(ASTNode astNode) {
 		CompilationUnit root = (CompilationUnit) astNode.getRoot();
 		for (IProblem problem : root.getProblems()) {
-			if (problem.isError()) {
-				hasErrors = true;
-				break;
-			}
+			if (problem.isError())
+				return true;
 		}
-		return hasErrors ? null : astNode;
+		return false;
 	}
 
-	private void tokenizeSource() {
+	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 */);
 		scanner.setSource(this.sourceArray);
+		scanner.fakeInModule = (kind & K_MODULE_INFO) != 0;
 		while (true) {
 			try {
 				int tokenType = scanner.getNextToken();
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 8b2028f..c38b76d 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
@@ -124,6 +124,7 @@
 	public int alignment_for_expressions_in_array_initializer;
 	public int alignment_for_expressions_in_for_loop_header;
 	public int alignment_for_method_declaration;
+	public int alignment_for_module_statements;
 	// TODO following option cannot be set in preferences dialog (but it's used by old.CodeFormatter)
 	public int alignment_for_multiple_fields;
 	public int alignment_for_parameterized_type_references;
@@ -460,6 +461,7 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER, getAlignment(this.alignment_for_expressions_in_array_initializer));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER, getAlignment(this.alignment_for_expressions_in_for_loop_header));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION, getAlignment(this.alignment_for_method_declaration));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS, getAlignment(this.alignment_for_module_statements));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS, getAlignment(this.alignment_for_multiple_fields));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES, getAlignment(this.alignment_for_parameterized_type_references));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_parameters_in_constructor_declaration));
@@ -897,6 +899,10 @@
 				this.alignment_for_method_declaration = Alignment.M_COMPACT_SPLIT;
 			}
 		}
+		final Object alignmentForModuleStatementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MODULE_STATEMENTS);
+		if (alignmentForModuleStatementsOption != null)
+			this.alignment_for_module_statements = toInt(alignmentForModuleStatementsOption, Alignment.M_COMPACT_SPLIT);
+
 		final Object alignmentForMultipleFieldsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS);
 		if (alignmentForMultipleFieldsOption != null) {
 			try {
@@ -2430,6 +2436,7 @@
 		this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_expressions_in_for_loop_header = Alignment.M_NO_ALIGNMENT;
 		this.alignment_for_method_declaration = Alignment.M_NO_ALIGNMENT;
+		this.alignment_for_module_statements = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_parameterized_type_references = Alignment.M_NO_ALIGNMENT;
 		this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
@@ -2740,6 +2747,7 @@
 		this.alignment_for_expressions_in_array_initializer = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_expressions_in_for_loop_header = Alignment.M_NO_ALIGNMENT;
 		this.alignment_for_method_declaration = Alignment.M_NO_ALIGNMENT;
+		this.alignment_for_module_statements = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_multiple_fields = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_parameterized_type_references = Alignment.M_NO_ALIGNMENT;
 		this.alignment_for_parameters_in_constructor_declaration = Alignment.M_COMPACT_SPLIT;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
index fb34029..ddf781b 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
@@ -60,6 +60,8 @@
 import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.MethodInvocation;
 import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.ModuleDeclaration;
+import org.eclipse.jdt.core.dom.ModuleStatement;
 import org.eclipse.jdt.core.dom.NormalAnnotation;
 import org.eclipse.jdt.core.dom.PackageDeclaration;
 import org.eclipse.jdt.core.dom.ReturnStatement;
@@ -674,6 +676,28 @@
 		return true;
 	}
 
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		// using settings for type declaration and fields for now, add new settings if necessary
+		breakLineBefore(node);
+		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
+				this.options.indent_body_declarations_compare_to_type_header,
+				this.options.insert_new_line_in_empty_type_declaration);
+
+		List<ModuleStatement> statements = node.moduleStatements();
+		ModuleStatement previous = null;
+		for (ModuleStatement statement : statements) {
+			int blankLines = previous == null ? this.options.blank_lines_before_first_class_body_declaration
+					: previous.getClass().equals(statement.getClass()) ? this.options.blank_lines_before_field
+							: this.options.blank_lines_before_new_chunk;
+			putBlankLinesBefore(statement, blankLines);
+			previous = statement;
+		}
+
+		this.declarationModifierVisited = false;
+		return true;
+	}
+
 	private void breakLineBefore(ASTNode node) {
 		this.tm.firstTokenIn(node, -1).breakBefore();
 	}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
index 1b94472..23bb472 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
@@ -40,6 +40,7 @@
 import org.eclipse.jdt.core.dom.EnhancedForStatement;
 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
 import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ExportsStatement;
 import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.ExpressionMethodReference;
 import org.eclipse.jdt.core.dom.ExpressionStatement;
@@ -56,12 +57,16 @@
 import org.eclipse.jdt.core.dom.MemberValuePair;
 import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.ModuleDeclaration;
+import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.OpensStatement;
 import org.eclipse.jdt.core.dom.PackageDeclaration;
 import org.eclipse.jdt.core.dom.ParameterizedType;
 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
 import org.eclipse.jdt.core.dom.PostfixExpression;
 import org.eclipse.jdt.core.dom.PrefixExpression;
+import org.eclipse.jdt.core.dom.ProvidesStatement;
 import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
 import org.eclipse.jdt.core.dom.ReturnStatement;
 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
@@ -363,7 +368,7 @@
 
 	@Override
 	public boolean visit(TryStatement node) {
-		List<VariableDeclarationExpression> resources = node.resources();
+		List<Expression> resources = node.resources();
 		if (!resources.isEmpty()) {
 			handleToken(node, TokenNameLPAREN, this.options.insert_space_before_opening_paren_in_try,
 					this.options.insert_space_after_opening_paren_in_try);
@@ -951,6 +956,37 @@
 		return true;
 	}
 
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		handleToken(node.getName(), TokenNameLBRACE,
+				this.options.insert_space_before_opening_brace_in_type_declaration, false);
+		return true;
+	}
+
+	@Override
+	public boolean visit(ExportsStatement node) {
+		handleModuleStatementCommas(node.modules());
+		return true;
+	}
+	
+	@Override
+	public boolean visit(OpensStatement node) {
+		handleModuleStatementCommas(node.modules());
+		return true;
+	}
+
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		handleModuleStatementCommas(node.implementations());
+		return true;
+	}
+
+	private void handleModuleStatementCommas(List<Name> names) {
+		// using settings for fields for now, add new settings if necessary
+		handleCommas(names, this.options.insert_space_before_comma_in_multiple_field_declarations,
+				this.options.insert_space_after_comma_in_multiple_field_declarations);
+	}
+
 	private void handleCommas(List<? extends ASTNode> nodes, boolean spaceBefore, boolean spaceAfter) {
 		if (spaceBefore || spaceAfter) {
 			for (int i = 1; i < nodes.size(); i++) {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index b45e6d4..5daa0d1 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -34,6 +34,8 @@
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamesuper;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethis;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethrows;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameto;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewith;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -55,6 +57,7 @@
 import org.eclipse.jdt.core.dom.CreationReference;
 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
 import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ExportsStatement;
 import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.ExpressionMethodReference;
 import org.eclipse.jdt.core.dom.FieldAccess;
@@ -67,8 +70,11 @@
 import org.eclipse.jdt.core.dom.LambdaExpression;
 import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.OpensStatement;
 import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.ProvidesStatement;
 import org.eclipse.jdt.core.dom.QualifiedName;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
 import org.eclipse.jdt.core.dom.Statement;
@@ -779,6 +785,34 @@
 		handleWrap(this.options.alignment_for_type_arguments);
 	}
 
+	@Override
+	public boolean visit(ExportsStatement node) {
+		handleModuleStatement(node.modules(), TokenNameto);
+		return true;
+	}
+
+	@Override
+	public boolean visit(OpensStatement node) {
+		handleModuleStatement(node.modules(), TokenNameto);
+		return true;
+	}
+
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		handleModuleStatement(node.implementations(), TokenNamewith);
+		return true;
+	}
+
+	private void handleModuleStatement(List<Name> names, int joiningTokenType) {
+		if (names.isEmpty())
+			return;
+		int joiningTokenIndex = this.tm.firstIndexBefore(names.get(0), joiningTokenType);
+		this.wrapParentIndex = this.tm.firstIndexBefore(names.get(0), TokenNameIdentifier);
+		this.wrapIndexes.add(joiningTokenIndex);
+		prepareElementsList(names, TokenNameCOMMA, -1);
+		handleWrap(this.options.alignment_for_module_statements, PREFERRED);
+	}
+
 	/**
 	 * Makes sure all new lines within given node will have wrap policy so that
 	 * wrap executor will fix their indentation if necessary.
@@ -1030,7 +1064,7 @@
 		int endingBreaks = getLineBreaksToPreserve(last, null, false);
 		if (endingBreaks > 0) {
 			last.putLineBreaksAfter(endingBreaks);
-		} else if ((this.kind & CodeFormatter.K_COMPILATION_UNIT) != 0
+		} else if ((this.kind & (CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.K_MODULE_INFO)) != 0
 				&& this.options.insert_new_line_at_end_of_file_if_missing) {
 			last.breakAfter();
 		}
diff --git a/org.eclipse.jdt.core/grammar/java.g b/org.eclipse.jdt.core/grammar/java.g
index 7b7ffde..41761de 100644
--- a/org.eclipse.jdt.core/grammar/java.g
+++ b/org.eclipse.jdt.core/grammar/java.g
@@ -48,7 +48,7 @@
 	interface long native new null package private
 	protected public return short static strictfp super switch
 	synchronized this throw throws transient true try void
-	volatile while
+	volatile while module open requires transitive exports opens to uses provides with
 
 	IntegerLiteral
 	LongLiteral
@@ -418,6 +418,120 @@
 /.$putCase consumeEmptyInternalCompilationUnit(); $break ./
 /:$readableName CompilationUnit:/
 
+--Java9 features
+InternalCompilationUnit ::= ImportDeclarations ReduceImports ModuleDeclaration
+/:$compliance 9:/
+/.$putCase consumeInternalCompilationUnitWithModuleDeclaration(); $break ./
+InternalCompilationUnit ::= ModuleDeclaration
+/:$compliance 9:/
+/.$putCase consumeInternalCompilationUnitWithModuleDeclaration(); $break ./
+ModuleDeclaration ::= ModuleHeader ModuleBody
+/:$compliance 9:/
+/.$putCase consumeModuleDeclaration(); $break ./
+
+-- to work around shift/reduce conflicts, we allow Modifiersopt in order to support annotations
+-- in a module declaration, and then report errors if any modifiers other than annotations are
+-- encountered
+ModuleHeader ::= Modifiersopt ModuleModifieropt 'module' UnannotatableName
+/:$compliance 9:/
+/.$putCase consumeModuleHeader(); $break ./
+ModuleModifieropt ::= $empty
+ModuleModifieropt ::= ModuleModifier
+/:$compliance 9:/
+/.$putCase consumeModuleModifiers(); $break ./
+ModuleModifier -> 'open'
+
+ModuleBody ::= '{' ModuleStatementsOpt '}'
+/:$compliance 9:/
+/:$no_statements_recovery:/
+ModuleStatementsOpt ::= $empty
+/:$compliance 9:/
+/.$putCase consumeEmptyModuleStatementsOpt(); $break ./
+ModuleStatementsOpt -> ModuleStatements
+/:$compliance 9:/
+ModuleStatements ::= ModuleStatement
+ModuleStatements ::= ModuleStatements ModuleStatement
+/:$compliance 9:/
+/.$putCase consumeModuleStatements(); $break ./
+
+ModuleStatement ::= RequiresStatement
+/:$compliance 9:/
+ModuleStatement ::= ExportsStatement
+/:$compliance 9:/
+ModuleStatement ::= OpensStatement
+/:$compliance 9:/
+ModuleStatement ::= UsesStatement
+/:$compliance 9:/
+ModuleStatement ::= ProvidesStatement
+/:$compliance 9:/
+
+RequiresStatement ::=  SingleRequiresModuleName ';'
+/:$compliance 9:/
+/.$putCase consumeRequiresStatement(); $break ./
+SingleRequiresModuleName ::= 'requires' RequiresModifiersopt UnannotatableName
+/:$compliance 9:/
+/.$putCase consumeSingleRequiresModuleName(); $break ./
+RequiresModifiersopt ::= RequiresModifiers
+/:$compliance 9:/
+/.$putCase consumeModifiers(); $break ./
+RequiresModifiersopt ::= $empty
+/:$compliance 9:/
+/.$putCase consumeDefaultModifiers(); $break ./
+RequiresModifiers -> RequiresModifier
+RequiresModifiers ::= RequiresModifiers RequiresModifier
+/:$compliance 9:/
+/.$putCase consumeModifiers2(); $break ./
+RequiresModifier -> 'transitive'
+RequiresModifier -> 'static'
+ExportsStatement ::=  ExportsHeader TargetModuleListopt ';'
+/:$compliance 9:/
+/.$putCase consumeExportsStatement(); $break ./
+ExportsHeader ::= 'exports' SinglePkgName
+/:$compliance 9:/
+/.$putCase consumeExportsHeader(); $break ./
+TargetModuleListopt ::= $empty
+TargetModuleListopt ::= 'to' TargetModuleNameList
+/:$compliance 9:/
+/.$putCase consumeTargetModuleList(); $break ./
+TargetModuleName ::= UnannotatableName
+/:$compliance 9:/
+/.$putCase consumeSingleTargetModuleName(); $break ./
+TargetModuleNameList -> TargetModuleName
+TargetModuleNameList ::= TargetModuleNameList ',' TargetModuleName
+/:$compliance 9:/
+/.$putCase consumeTargetModuleNameList(); $break ./
+SinglePkgName ::= UnannotatableName
+/:$compliance 9:/
+/.$putCase consumeSinglePkgName(); $break ./
+OpensStatement ::=  OpensHeader TargetModuleListopt ';'
+/:$compliance 9:/
+/.$putCase consumeOpensStatement(); $break ./
+OpensHeader ::= 'opens' SinglePkgName
+/:$compliance 9:/
+/.$putCase consumeOpensHeader(); $break ./
+UsesStatement ::=  UsesHeader ';'
+/:$compliance 9:/
+/.$putCase consumeUsesStatement(); $break ./
+UsesHeader ::= 'uses' Name
+/.$putCase consumeUsesHeader(); $break ./
+ProvidesStatement ::= ProvidesInterface WithClause ';'
+/:$compliance 9:/
+/.$putCase consumeProvidesStatement(); $break ./
+ProvidesInterface ::= 'provides' Name
+/:$compliance 9:/
+/.$putCase consumeProvidesInterface(); $break ./
+ServiceImplName ::= Name
+/:$compliance 9:/
+/.$putCase consumeSingleServiceImplName(); $break ./
+ServiceImplNameList -> ServiceImplName
+ServiceImplNameList ::= ServiceImplNameList ',' ServiceImplName
+/:$compliance 9:/
+/.$putCase consumeServiceImplNameList(); $break ./
+
+WithClause ::= 'with' ServiceImplNameList
+/:$compliance 9:/
+/.$putCase consumeWithClause(); $break ./
+
 ReduceImports ::= $empty
 /.$putCase consumeReduceImports(); $break ./
 /:$readableName ReduceImports:/
@@ -437,6 +551,12 @@
 Header -> FieldDeclaration
 Header -> AllocationHeader
 Header -> ArrayCreationHeader
+Header -> ModuleHeader
+Header -> RequiresStatement
+Header -> ExportsStatement
+Header -> UsesStatement
+Header -> ProvidesStatement
+Header -> OpensStatement
 /:$readableName Header:/
 
 Header1 -> Header
@@ -1284,6 +1404,16 @@
 /:$readableName Resource:/
 /:$compliance 1.7:/
 
+Resource ::= Name
+/.$putCase consumeResourceAsLocalVariable(); $break ./
+/:$readableName Resource:/
+/:$compliance 1.9:/
+
+Resource ::= FieldAccess
+/.$putCase consumeResourceAsFieldAccess(); $break ./
+/:$readableName Resource:/
+/:$compliance 1.9:/
+
 TryBlock ::= Block ExitTryBlock
 /:$readableName Block:/
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
index b1a8f42..077d415 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -872,6 +876,30 @@
 	public static final int ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION = 27;
 
 	/**
+	 * Completion is a declaration of a module.
+	 * This kind of completion might occur in a module-info.java file
+	 * after the keyword <code> "module" </code> as shown below:
+	 * <code>"module co^"</code> and complete it to
+	 * <code>"module com.greetings"</code>.
+	 *
+	 * @see #getKind()
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int MODULE_DECLARATION = 28;
+
+	/**
+	/**
+	 * Completion is a reference to a module.
+	 * This kind of completion might occur in a context like
+	 * <code>"requires com.g^"</code> and complete it to
+	 * <code>"requires com.greetings"</code> or in
+	 * <code> "to com.g^"</code> to <code>"to com.greetings</code>
+	 *
+	 * @see #getKind()
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static final int MODULE_REF = 29;
+	/**
 	 * First valid completion kind.
 	 *
 	 * @since 3.1
@@ -883,7 +911,7 @@
 	 *
 	 * @since 3.1
 	 */
-	protected static final int LAST_KIND = ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION;
+	protected static final int LAST_KIND = MODULE_REF;
 
 	/**
 	 * Creates a basic completion proposal. All instance
@@ -1155,7 +1183,7 @@
 	}
 
 	/**
-	 * Returns the type signature or package name of the relevant
+	 * Returns the type signature or package name or module name (1.9) of the relevant
 	 * declaration in the context, or <code>null</code> if none.
 	 * <p>
 	 * This field is available for the following kinds of
@@ -1180,6 +1208,8 @@
 	 * 	<li><code>METHOD_DECLARATION</code> - type signature
 	 * of the type that declares the method that is being
 	 * implemented or overridden</li>
+	 * 	<li><code>MODULE_REF</code> - 
+	 * name of the module that is referenced</li>
 	 * 	<li><code>PACKAGE_REF</code> - dot-based package
 	 * name of the package that is referenced</li>
 	 * 	<li><code>TYPE_IMPORT</code> - dot-based package
@@ -1194,7 +1224,7 @@
 	 * returned.
 	 * </p>
 	 *
-	 * @return a type signature or a package name (depending
+	 * @return a type signature or a package name or module name (1.9) (depending
 	 * on the kind of completion), or <code>null</code> if none
 	 * @see Signature
 	 */
@@ -1230,7 +1260,7 @@
 	}
 
 	/**
-	 * Sets the type or package signature of the relevant
+	 * Sets the type or package or module(1.9) signature of the relevant
 	 * declaration in the context, or <code>null</code> if none.
 	 * <p>
 	 * If not set, defaults to none.
@@ -1240,7 +1270,7 @@
 	 * its properties; this method is not intended to be used by other clients.
 	 * </p>
 	 *
-	 * @param signature the type or package signature, or
+	 * @param signature the type or package  or module(1.9) signature, or
 	 * <code>null</code> if none
 	 */
 	public void setDeclarationSignature(char[] signature) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
index 9bab66c..3da4369 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- *
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -113,6 +117,16 @@
 	 * @since 3.2
 	 */
 	String OPTIONAL = "optional"; //$NON-NLS-1$
+	/**
+	 * Constant for the name of automatic module. The possible values
+	 * for this attribute are <code>"true"</code> or <code>"false"</code>.
+	 * When not present, <code>"false"</code> is assumed.
+	 * If the value of this attribute is <code>"true"</code>, the classpath entry
+	 * is considered to be an automatic module.
+	 *
+	 * @since 3.13 BETA_JAVA9
+	 */
+	String AUTOMATIC_MODULE = "module"; //$NON-NLS-1$
 
 	/**
 	 * Constant for the name of the external annotation path attribute. 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
index 8c882fd..2946d65 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
index 62b9372..1ae4d5f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -132,6 +136,14 @@
 	int ANNOTATION = 16;
 
 	/**
+	 * Constant represents a module descriptor.
+	 * A Java element with this type can be safely cast to {@link IModuleDescription}.
+	 *
+	 * @since 3.13 BETA_JAVA9
+	 */
+	int JAVA_MODULE = 17;
+
+	/**
 	 * Returns whether this Java element exists in the model.
 	 * <p>
 	 * Java elements are handle objects that may or may not be backed by an
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
index b891c7a..2f13219 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
@@ -576,6 +576,18 @@
 	IProject getProject();
 
 	/**
+	 * Returns the <code>IModuleDescription</code> this project represents or 
+	 * null if the Java project doesn't represent any named module. A Java 
+	 * project is said to represent a module if any of its source package 
+	 * fragment roots (see {@link IPackageFragmentRoot#K_SOURCE}) contains a 
+	 * valid Java module descriptor.
+	 * 
+	 * @return the <code>IModule</code> this project represents.
+	 * @since 3.13 BETA_JAVA9
+	 */
+	IModuleDescription getModuleDescription() throws JavaModelException;
+
+	/**
 	 * Returns the raw classpath for the project, as a list of classpath
 	 * entries. This corresponds to the exact set of entries which were assigned
 	 * using <code>setRawClasspath</code>, in particular such a classpath may
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java
new file mode 100644
index 0000000..b699f61
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IModuleDescription.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+/**
+ * Represents a Java module descriptor. The module description could either come from source or binary.
+ * A simple module looks like the following:
+ * <pre>
+ * module my.module {
+ * 		exports my.pack1;
+ * 		exports my.pack2;
+ * 		requires java.sql;
+ * }
+ * </pre>
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 3.13 BETA_JAVA9
+ */
+public interface IModuleDescription extends IMember {
+	// empty block
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
index c1ed588..02b1d5e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     IBM Corporation - specified that a source archive or a source folder can be attached to a binary
@@ -446,4 +450,19 @@
 	 * @since 2.1
 	 */
 	void move(IPath destination, int updateResourceFlags, int updateModelFlags, IClasspathEntry sibling, IProgressMonitor monitor) throws JavaModelException;
+
+	/**
+	 * Returns the <code>IModuleDescription</code> that this package fragment root contains 
+	 * or <code>null</code> if the root doesn't contain any named module. The package fragment
+	 * root may contain the module descriptor directly in its default package or in the case
+	 * of a source package fragment root, it may come from any of the other source package
+	 * fragment roots in the Java project.
+	 * 
+	 * Note that only one of the source package fragment roots in a Java Project can legally
+	 * contain a module descriptor.
+	 *
+	 * @return the <code>IModuleDescription</code> this root contains.
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public IModuleDescription getModuleDescription();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java
index 97ebff6..b591043 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java
@@ -33,7 +33,15 @@
  * @return the found primary type of this Java type root, or <code>null</code> if no such a type exists
  */
 IType findPrimaryType();
-
+/**
+ * Returns the module description contained in this type root or null if there is no module
+ * in this type root.
+ *
+ * @throws JavaModelException 
+ * @since 3.13 BETA_JAVA9
+ * @return the module description contained in the type root or null.
+ */
+IModuleDescription getModule() throws JavaModelException;
 /**
  * Returns the smallest element within this Java type root that
  * includes the given source position (that is, a method, field, etc.), or
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index 79c9b69..6cc57c5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -38,7 +42,6 @@
 public final class JavaConventions {
 
 	private static final char DOT= '.';
-	private static final String PACKAGE_INFO = new String(TypeConstants.PACKAGE_INFO_NAME);
 	private static final Scanner SCANNER = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
 
 	private JavaConventions() {
@@ -157,7 +160,8 @@
 		// JSR-175 metadata strongly recommends "package-info.java" as the
 		// file in which to store package annotations and
 		// the package-level spec (replaces package.html)
-		if (!identifier.equals(PACKAGE_INFO)) {
+		if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME)
+				&& !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) {
 			IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
 			if (!status.isOK()) {
 				return status;
@@ -229,7 +233,8 @@
 		// JSR-175 metadata strongly recommends "package-info.java" as the
 		// file in which to store package annotations and
 		// the package-level spec (replaces package.html)
-		if (!identifier.equals(PACKAGE_INFO)) {
+		if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME)
+				&& !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) {
 			IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
 			if (!status.isOK()) {
 				return status;
@@ -408,6 +413,7 @@
 	 * @see JavaCore#VERSION_1_6
 	 * @see JavaCore#VERSION_1_7
 	 * @see JavaCore#VERSION_1_8
+	 * @see JavaCore#VERSION_9
 	 */
 	public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel) {
 		if (name == null) {
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 db6d24b..44a8946 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     IBM Corporation - added the following constants:
@@ -174,6 +178,7 @@
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.ModuleUtil;
 import org.eclipse.jdt.internal.core.util.Util;
 import org.osgi.framework.BundleContext;
 
@@ -240,6 +245,11 @@
 	 */
 	public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.jdt.USER_LIBRARY"; //$NON-NLS-1$
 
+	/**
+	 * @since 3.13
+	 */
+	public static final String MODULE_PATH_CONTAINER_ID = "org.eclipse.jdt.MODULE_PATH"; //$NON-NLS-1$
+
 	// Begin configurable option IDs {
 
 	/**
@@ -313,7 +323,7 @@
 	 * <p><code>"cldc1.1"</code> requires the source version to be <code>"1.3"</code> and the compliance version to be <code>"1.4"</code> or lower.</p>
 	 * <dl>
 	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.codegen.targetPlatform"</code></dd>
-	 * <dt>Possible values:</dt><dd><code>{ "1.1", "cldc1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }</code></dd>
+	 * <dt>Possible values:</dt><dd><code>{ "1.1", "cldc1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }</code></dd>
 	 * <dt>Default:</dt><dd><code>"1.2"</code></dd>
 	 * </dl>
 	 * @category CompilerOptionID
@@ -1975,7 +1985,7 @@
 	 *    set to the same version as the source level.</p>
 	 * <dl>
 	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.source"</code></dd>
-	 * <dt>Possible values:</dt><dd><code>{ "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }</code></dd>
+	 * <dt>Possible values:</dt><dd><code>{ "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }</code></dd>
 	 * <dt>Default:</dt><dd><code>"1.3"</code></dd>
 	 * </dl>
 	 * @since 2.0
@@ -1993,7 +2003,7 @@
 	 *    should match the compliance setting.</p>
 	 * <dl>
 	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.compliance"</code></dd>
-	 * <dt>Possible values:</dt><dd><code>{ "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" }</code></dd>
+	 * <dt>Possible values:</dt><dd><code>{ "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "9" }</code></dd>
 	 * <dt>Default:</dt><dd><code>"1.4"</code></dd>
 	 * </dl>
 	 * @since 2.0
@@ -2894,6 +2904,12 @@
 	public static final String VERSION_1_8 = "1.8"; //$NON-NLS-1$
 	/**
 	 * Configurable option value: {@value}.
+	 * @since 3.13 BETA_JAVA9
+	 * @category OptionValue
+	 */
+	public static final String VERSION_9 = "9"; //$NON-NLS-1$
+	/**
+	 * Configurable option value: {@value}.
 	 * @since 3.4
 	 * @category OptionValue
 	 */
@@ -5846,6 +5862,14 @@
 				options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR);
 				options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED);
 				break;
+			case ClassFileConstants.MAJOR_VERSION_9:
+				options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_9);
+				options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_9);
+				options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_9);
+				options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
+				options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR);
+				options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED);
+				break;
 		}
 	}
 
@@ -5888,6 +5912,27 @@
 	public static int compareJavaVersions(String first, String second) {
 		return Long.compare(CompilerOptions.versionToJdkLevel(first), CompilerOptions.versionToJdkLevel(second));
 	}
+	/**
+	 * Returns an array of module names referenced by this project indirectly. 
+	 * This is a helper method that can be used to construct a Java module 
+	 * description of an existing project. The referenced modules can either be 
+	 * system modules or user modules found in project build path in the form of 
+	 * libraries.
+	 * The prerequisites for this to be effective are:
+	 * <ul>
+	 * <li>the project is already in compliance level 9 or above.
+	 * <li>the system library on the build path of the project is a modularized Java Runtime.
+	 * </ul>
+	 *
+	 * @param project
+	 *            the project whose referenced modules to be computed
+	 * @return an array of String containing module names
+	 * @throws CoreException
+	 * @since 3.13 BETA_JAVA9
+	 */
+	public static String[] getReferencedModules(IJavaProject project) throws CoreException {
+		return ModuleUtil.getReferencedModules(project);
+	}
 
 	/* (non-Javadoc)
 	 * Shutdown the JavaCore plug-in.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
index bb6d6c4..6a05b00 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -71,6 +71,15 @@
 public JavaModelException(IJavaModelStatus status) {
 	super(status);
 }
+
+/**
+ * Creates a Java model exception for the given status object.
+ *
+ * @since 3.13 BETA_JAVA9
+ */
+public JavaModelException(IStatus status) {
+	super(status);
+}
 /**
  * Returns the underlying <code>Throwable</code> that caused the failure.
  *
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
index 38eca3b..9b2d9d6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2013 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -88,20 +88,9 @@
  * with JLS4 level.
  */
 public org.eclipse.jdt.core.dom.CompilationUnit getAST3() throws JavaModelException {
-	if (this.operation.astLevel != AST.JLS3 || !this.operation.resolveBindings) {
-		// create AST (optionally resolving bindings)
-		ASTParser parser = ASTParser.newParser(AST.JLS3);
-		parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true));
-		if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject()))
-			parser.setResolveBindings(true);
-		parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
-		parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
-		parser.setSource(this.workingCopy);
-		parser.setIgnoreMethodBodies((this.operation.reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
-		return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor);
-	}
-	return this.operation.makeConsistent(this.workingCopy);
+	return getAST(AST.JLS3);
 }
+
 /**
  * Returns a resolved AST with {@link AST#JLS4 JLS4} level.
  * It is created from the current state of the working copy.
@@ -128,20 +117,9 @@
  * @since 3.7.1
  */
 public org.eclipse.jdt.core.dom.CompilationUnit getAST4() throws JavaModelException {
-	if (this.operation.astLevel != AST.JLS4 || !this.operation.resolveBindings) {
-		// create AST (optionally resolving bindings)
-		ASTParser parser = ASTParser.newParser(AST.JLS4);
-		parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true));
-		if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject()))
-			parser.setResolveBindings(true);
-		parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
-		parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
-		parser.setSource(this.workingCopy);
-		parser.setIgnoreMethodBodies((this.operation.reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
-		return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor);
-	}
-	return this.operation.makeConsistent(this.workingCopy);
+	return getAST(AST.JLS4);
 }
+
 /**
  * Returns a resolved AST with {@link AST#JLS8 JLS8} level.
  * It is created from the current state of the working copy.
@@ -163,12 +141,43 @@
  * <ul>
  * <li> The working copy does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * </ul>
+ * @deprecated JLS8 has been deprecated. This method has been replaced by {@link #getAST(int)} which returns an AST
+ * with the given level.
  * @since 3.10
  */
 public org.eclipse.jdt.core.dom.CompilationUnit getAST8() throws JavaModelException {
-	if (this.operation.astLevel != AST.JLS8 || !this.operation.resolveBindings) {
+	return getAST(AST.JLS8);
+}
+
+/**
+ * Returns a resolved AST with the given AST level.
+ * It is created from the current state of the working copy.
+ * Creates one if none exists yet.
+ * Returns <code>null</code> if the current state of the working copy
+ * doesn't allow the AST to be created (e.g. if the working copy's content
+ * cannot be parsed).
+ * <p>
+ * If the AST level requested during reconciling is not the latest available AST level
+ * or if binding resolutions was not requested, then a different AST is created.
+ * Note that this AST does not become the current AST and it is only valid for
+ * the requestor.
+ * </p>
+ *
+ * @param level the API level; one of the <code>.JLS*</code> level constants
+ * declared on {@link AST}
+ * @return the AST created from the current state of the working copy,
+ *   or <code>null</code> if none could be created
+ * @exception JavaModelException  if the contents of the working copy
+ *		cannot be accessed. Reasons include:
+ * <ul>
+ * <li> The working copy does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @since 3.13 BETA_JAVA9
+ */
+public org.eclipse.jdt.core.dom.CompilationUnit getAST(int level) throws JavaModelException {
+	if (this.operation.astLevel != level || !this.operation.resolveBindings) {
 		// create AST (optionally resolving bindings)
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(level);
 		parser.setCompilerOptions(this.workingCopy.getJavaProject().getOptions(true));
 		if (JavaProject.hasJavaNature(this.workingCopy.getJavaProject().getProject()))
 			parser.setResolveBindings(true);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
index c301b3b..c1f5ec1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -52,6 +52,7 @@
         case AST.JLS3 :
         case AST.JLS4 :
         case AST.JLS8 :
+        case AST.JLS9 :
             break;
         default :
             throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index 42fd7d6..8ca1eeb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -18,6 +22,7 @@
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 
 /*
@@ -27,7 +32,8 @@
  *
  * The structural investigation includes: - package statement - import
  * statements - top-level types: package member, member types (member types of
- * member types...) - fields - methods
+ * member types...) - fields - methods. From Java 9 onwards it includes the 
+ * module name in a module declaration
  *
  * If reference information is requested, then all source constructs are
  * investigated and type, field & method references are provided as well.
@@ -46,6 +52,33 @@
 @SuppressWarnings("rawtypes")
 public interface ISourceElementRequestor {
 
+	public static class ModuleInfo {
+		public int declarationStart;
+		public int modifiers;
+		public char[] name;
+		public int nameSourceStart;
+		public int nameSourceEnd;
+		public char[] moduleName;
+		public RequiresInfo[] requires;
+		public PackageExportInfo[] exports;
+		public ServicesInfo[] services;
+		public PackageExportInfo[] opens;
+		public char[][] usedServices;
+		public Annotation[] annotations;
+		public ModuleDeclaration node;
+	}
+	public static class RequiresInfo {
+		public char[] moduleName;
+		public int modifiers;
+	}
+	public static class PackageExportInfo {
+		public char[] pkgName;
+		public char[][] targets;
+	}
+	public static class ServicesInfo {
+		public char[] serviceName;
+		public char[][] implNames;
+	}
 	public static class TypeInfo {
 		public boolean typeAnnotated;
 		public int declarationStart;
@@ -200,4 +233,11 @@
 	void exitMethod(int declarationEnd, Expression defaultValue);
 
 	void exitType(int declarationEnd);
+	
+	default void enterModule(ModuleInfo info) {
+		// do nothing
+	}
+	default void exitModule(int declarationEnd) {
+		// do nothing
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
index 54d7a09..b35eb20 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementNotifier.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2015 IBM Corporation and others.
+ * Copyright (c) 2008, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -31,12 +35,15 @@
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.ThisReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -457,7 +464,12 @@
 						notifySourceElementRequestor(importRef, false);
 					}
 				} else { // instanceof TypeDeclaration
-					notifySourceElementRequestor((TypeDeclaration)node, true, null, currentPackage);
+					TypeDeclaration type = (TypeDeclaration) node;
+					if (type.isModuleInfo()) {
+						notifySourceElementRequestor(parsedUnit.moduleDeclaration);
+					} else {
+						notifySourceElementRequestor((TypeDeclaration)node, true, null, currentPackage);
+					}
 				}
 			}
 		}
@@ -576,6 +588,31 @@
 			importReference.modifiers);
 	}
 }
+protected void notifySourceElementRequestor(ModuleDeclaration moduleDeclaration) {
+	boolean isInRange =
+			this.initialPosition <= moduleDeclaration.declarationSourceStart
+			&& this.eofPosition >= moduleDeclaration.declarationSourceEnd;
+	ISourceElementRequestor.ModuleInfo info = new ISourceElementRequestor.ModuleInfo();
+	if (isInRange) {
+
+		int currentModifiers = moduleDeclaration.modifiers;
+
+		// remember deprecation so as to not lose it below
+		boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(moduleDeclaration.annotations);
+
+		info.declarationStart = moduleDeclaration.declarationSourceStart;
+		info.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+		info.name = TypeConstants.MODULE_INFO_NAME;
+		info.nameSourceStart = moduleDeclaration.sourceStart;
+		info.nameSourceEnd = moduleDeclaration.sourceEnd;
+		info.moduleName = moduleDeclaration.moduleName;
+		info.annotations = moduleDeclaration.annotations;
+		info.node = moduleDeclaration;
+		fillModuleInfo(moduleDeclaration, info);
+		this.requestor.enterModule(info);
+		this.requestor.exitModule(moduleDeclaration.declarationSourceEnd);
+	}
+}
 protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType, ImportReference currentPackage) {
 
 	if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return;
@@ -711,6 +748,74 @@
 		this.nestedTypeIndex--;
 	}
 }
+private void fillModuleInfo(ModuleDeclaration mod, ISourceElementRequestor.ModuleInfo modInfo) {
+	if (mod.requiresCount > 0) {
+		ISourceElementRequestor.RequiresInfo reqs[] = new ISourceElementRequestor.RequiresInfo[mod.requiresCount];
+		for (int i = 0; i < mod.requiresCount; i++) {
+			ISourceElementRequestor.RequiresInfo req = new ISourceElementRequestor.RequiresInfo();
+			req.moduleName = CharOperation.concatWith(mod.requires[i].module.tokens, '.');
+			req.modifiers = mod.requires[i].modifiers;
+			reqs[i] = req;
+		}
+		modInfo.requires = reqs;
+	}
+	if (mod.exportsCount > 0) {
+		ISourceElementRequestor.PackageExportInfo exps[] = new ISourceElementRequestor.PackageExportInfo[mod.exportsCount];
+		for (int i = 0; i < mod.exportsCount; i++) {
+			ISourceElementRequestor.PackageExportInfo exp = new ISourceElementRequestor.PackageExportInfo();
+			ExportsStatement exportsStatement = mod.exports[i];
+			exp.pkgName = exportsStatement.pkgName;
+			if (exportsStatement.targets == null) {
+				exp.targets = CharOperation.NO_CHAR_CHAR;
+			} else {
+				exp.targets = new char[exportsStatement.targets.length][];
+				for(int j = 0; j < exp.targets.length; j++) {
+					exp.targets[j] = CharOperation.concatWith(exportsStatement.targets[j].tokens, '.');
+				}
+			}
+			exps[i] = exp;
+		}					
+		modInfo.exports = exps;
+	}
+	if (mod.servicesCount > 0) {
+		ISourceElementRequestor.ServicesInfo[] services = new ISourceElementRequestor.ServicesInfo[mod.servicesCount];
+		for (int i = 0; i < services.length; i++) {
+			ISourceElementRequestor.ServicesInfo ser = new ISourceElementRequestor.ServicesInfo();
+			ser.serviceName = CharOperation.concatWith(mod.services[i].serviceInterface.getParameterizedTypeName(), '.');
+			ser.implNames = new char[mod.services[i].implementations.length][];
+			for (int j = 0; j < ser.implNames.length; j++) {
+				ser.implNames[j] = CharOperation.concatWith(mod.services[i].implementations[j].getParameterizedTypeName(), '.');
+			}
+			services[i] = ser;
+		}
+		modInfo.services = services;
+	}
+	if (mod.usesCount > 0) {
+		char[][] uses = new char[mod.usesCount][];
+		for (int i = 0; i < uses.length; i++) {
+			uses[i] = CharOperation.concatWith(mod.uses[i].serviceInterface.getParameterizedTypeName(), '.');
+		}
+		modInfo.usedServices = uses;
+	}
+	if (mod.opensCount > 0) {
+		ISourceElementRequestor.PackageExportInfo opens[] = new ISourceElementRequestor.PackageExportInfo[mod.opensCount];
+		for (int i = 0; i < mod.opensCount; i++) {
+			ISourceElementRequestor.PackageExportInfo op = new ISourceElementRequestor.PackageExportInfo();
+			OpensStatement openStmt = mod.opens[i];
+			op.pkgName = openStmt.pkgName;
+			if (openStmt.targets == null) {
+				op.targets = CharOperation.NO_CHAR_CHAR;
+			} else {
+				op.targets = new char[openStmt.targets.length][];
+				for(int j = 0; j < op.targets.length; j++) {
+					op.targets[j] = CharOperation.concatWith(openStmt.targets[j].tokens, '.');
+				}
+			}
+			opens[i] = op;
+		}
+		modInfo.opens = opens;
+	}
+}
 /*
  * Sort the given ast nodes by their positions.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 2176f1e..ed05aa8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -536,6 +540,12 @@
 		this.requestor.acceptAnnotationTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd);
 	}
 }
+protected void consumeProvidesStatement() {
+	super.consumeProvidesStatement();
+	ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr];
+	TypeReference ref = service.serviceInterface;
+	this.requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+}
 protected void consumeSingleMemberAnnotation(boolean isTypeAnnotation) {
 	super.consumeSingleMemberAnnotation(isTypeAnnotation);
 	SingleMemberAnnotation member = (SingleMemberAnnotation) (isTypeAnnotation ? this.typeAnnotationStack[this.typeAnnotationPtr] : this.expressionStack[this.expressionPtr]);
@@ -718,6 +728,19 @@
 		this.requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 	}
 }
+protected void consumeUsesStatement() {
+	super.consumeUsesStatement();
+	UsesStatement ref = (UsesStatement) this.astStack[this.astPtr];
+	this.requestor.acceptTypeReference(ref.serviceInterface.getTypeName(), ref.sourceStart, ref.sourceEnd);
+}
+protected void consumeWithClause() {
+	super.consumeWithClause();
+	ProvidesStatement service = (ProvidesStatement) this.astStack[this.astPtr];
+		for (int i = 0; i < service.implementations.length; i++) {
+			TypeReference ref = service.implementations[i];
+			this.requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+		}
+}
 public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
 	MethodDeclaration methodDeclaration = super.convertToMethodDeclaration(c, compilationResult);
 	int selectorSourceEnd = this.sourceEnds.removeKey(c);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index d9b6611..ff05146 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -114,7 +114,6 @@
 		SourceTypeElementInfo topLevelTypeInfo = (SourceTypeElementInfo) sourceTypes[0];
 		org.eclipse.jdt.core.ICompilationUnit cuHandle = topLevelTypeInfo.getHandle().getCompilationUnit();
 		this.cu = (ICompilationUnit) cuHandle;
-
 		final CompilationUnitElementInfo compilationUnitElementInfo = (CompilationUnitElementInfo) ((JavaElement) this.cu).getElementInfo();
 		if (this.has1_5Compliance && 
 				(compilationUnitElementInfo.annotationNumber >= CompilationUnitElementInfo.ANNOTATION_THRESHOLD_FOR_DIET_PARSE ||
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java
new file mode 100644
index 0000000..84a90d9
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.compiler.env.IModule.IService;
+
+public abstract class AbstractModule extends NamedMember implements IModuleDescription {
+	protected AbstractModule(JavaElement parent, String name) {
+		super(parent, name);
+	}
+	public IModuleReference[] getRequiredModules() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.requires();
+	}
+	public IPackageExport[] getExportedPackages() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.exports();
+	}
+	public IService[] getProvidedServices() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.provides();
+	}
+	public char[][] getUsedServices() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.uses();
+	}
+	public IPackageExport[] getOpenedPackages() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.opens();
+	}
+	public String getKey(boolean forceOpen) throws JavaModelException {
+		return getKey(this, forceOpen);
+	}
+	public String toString(String lineDelimiter) {
+		StringBuffer buffer = new StringBuffer();
+		try {
+			toStringContent(buffer, lineDelimiter);
+		} catch (JavaModelException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer, String lineDelimiter) throws JavaModelException {
+		IPackageExport[] exports = getExportedPackages();
+		IModuleReference[] requires = getRequiredModules();
+		buffer.append("module "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append(lineDelimiter);
+		if (exports != null) {
+			for(int i = 0; i < exports.length; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(exports[i].toString());
+				buffer.append(lineDelimiter);
+			}
+		}
+		buffer.append(lineDelimiter);
+		if (requires != null) {
+			for(int i = 0; i < requires.length; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (requires[i].isTransitive()) {
+					buffer.append(" public "); //$NON-NLS-1$
+				}
+				buffer.append(requires[i].name());
+				buffer.append(';').append(lineDelimiter);
+			}
+		}
+		buffer.append(lineDelimiter).append('}').toString();
+	}
+
+	/**
+	 * @see JavaElement#getHandleMemento()
+	 */
+	protected char getHandleMementoDelimiter() {
+		return JavaElement.JEM_MODULE;
+	}
+	@Override
+	public int getElementType() {
+		return JAVA_MODULE;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
index 11cdaa3..7b9983c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -115,7 +119,7 @@
 		int start = CharOperation.lastIndexOf('/', this.fileName) + 1;
 		if (start == 0 || start < CharOperation.lastIndexOf('\\', this.fileName))
 			start = CharOperation.lastIndexOf('\\', this.fileName) + 1;
-		int separator = CharOperation.indexOf('|', this.fileName) + 1;
+		int separator = CharOperation.lastIndexOf('|', this.fileName) + 1;
 		if (separator > start) // case of a .class file in a default package in a jar
 			start = separator;
 
@@ -139,4 +143,10 @@
 public String toString(){
 	return "CompilationUnit: "+new String(this.fileName); //$NON-NLS-1$
 }
+
+@Override
+public char[] module() {
+	// TODO Auto-generated method stub
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java
new file mode 100644
index 0000000..422db16
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaModelException;
+
+public class BinaryModule extends AbstractModule {
+	public BinaryModule(JavaElement parent, String name) {
+		super(parent, name);
+	}
+	/*
+	 * @see IParent#getChildren()
+	 */
+	public IJavaElement[] getChildren() throws JavaModelException {
+		ClassFile cf = (ClassFile) this.parent;
+		ClassFileInfo cfi = (ClassFileInfo) cf.getElementInfo();
+		return cfi.binaryChildren;
+	}
+	@Override
+	public int getFlags() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.getModifiers();
+	}
+	public String getKey(boolean forceOpen) throws JavaModelException {
+		return getKey(this, forceOpen);
+	}
+	public String toString(String lineDelimiter) {
+		StringBuffer buffer = new StringBuffer();
+		try {
+			toStringContent(buffer, lineDelimiter);
+		} catch (JavaModelException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
index 3236b32..9826cfd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -15,6 +19,7 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
@@ -45,15 +50,13 @@
 		return super.findType(name, packageName);
 	}
 
-	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes) {
-		return findType(typeName, packageName);
-	}
-
 	public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
 		checkCanceled();
 		return super.findType(compoundTypeName);
 	}
-
+	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, IModuleContext context) {
+		return findType(typeName, packageName);
+	}
 	public void findTypes(char[] prefix, boolean findMembers, boolean camelCaseMatch, int searchFor, ISearchRequestor storage, IProgressMonitor progressMonitor) {
 		checkCanceled();
 		super.findTypes(prefix, findMembers, camelCaseMatch, searchFor, storage, progressMonitor);
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 cee25a9..a73205a 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -14,6 +18,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,10 +39,13 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IDependent;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.nd.java.JavaNames;
 import org.eclipse.jdt.internal.core.nd.java.model.BinaryTypeDescriptor;
@@ -102,15 +110,17 @@
 		info.setChildren(new IJavaElement[] {});
 		return false;
 	}
-
+	
 	// Make the type
 	IType type = getType();
 	info.setChildren(new IJavaElement[] {type});
 	newElements.put(type, typeInfo);
-
 	// Read children
 	((ClassFileInfo) info).readBinaryChildren(this, (HashMap) newElements, typeInfo);
-
+	BinaryModule mod = (BinaryModule) ((ClassFileInfo) info).getModule();
+	if (mod != null) {
+		((PackageFragmentRootInfo) getPackageFragmentRoot().getElementInfo()).setModule(mod);
+	}
 	return true;
 }
 /**
@@ -318,15 +328,12 @@
 	JavaElement pkg = (JavaElement) getParent();
 	if (pkg instanceof JarPackageFragment) {
 		JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent();
-		ZipFile zip = null;
 		try {
-			zip = root.getJar();
 			String entryName = Util.concatWith(((PackageFragment) pkg).names, getElementName(), '/');
-			ZipEntry ze = zip.getEntry(entryName);
-			if (ze != null) {
-				return org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
-			}
-			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+			entryName = root.getClassFilePath(entryName);
+			return getClassFileContent(root, entryName);
+			// BETA_JAVA9 - The below exception is not thrown in new scheme of things. Could cause issues?
+//			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 		} catch (IOException ioe) {
 			throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION);
 		} catch (CoreException e) {
@@ -335,14 +342,37 @@
 			} else {
 				throw new JavaModelException(e);
 			}
-		} finally {
-			JavaModelManager.getJavaModelManager().closeZipFile(zip);
 		}
 	} else {
 		IFile file = (IFile) resource();
 		return Util.getResourceContentsAsByteArray(file);
 	}
 }
+private byte[] getClassFileContent(JarPackageFragmentRoot root, String className) throws CoreException, IOException {
+	byte[] contents = null;
+	String rootPath = root.getPath().toOSString();
+	if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) {
+			try {
+				contents = org.eclipse.jdt.internal.compiler.util.JRTUtil.getClassfileContent(
+						new File(rootPath),
+						className,
+						root.getElementName());
+			} catch (ClassFormatException e) {
+				e.printStackTrace();
+			}
+	} else {
+		ZipFile zip = root.getJar();
+		try {
+			ZipEntry ze = zip.getEntry(className);
+			if (ze != null) {
+				contents = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
+			}
+		} finally {
+			JavaModelManager.getJavaModelManager().closeZipFile(zip);
+		}
+	}
+	return contents;
+}
 
 public String getName() {
 	return this.name;
@@ -354,33 +384,52 @@
 	if (descriptor == null) {
 		return null;
 	}
-
-	IBinaryType result = BinaryTypeFactory.readType(descriptor, null);
-
+	IBinaryType result = null;
+	IPackageFragmentRoot root = getPackageFragmentRoot();
+	if (getPackageFragmentRoot() instanceof JarPackageFragmentRoot) {
+		if (root instanceof JrtPackageFragmentRoot || this.name.equals(IModuleEnvironment.MODULE_INFO)) {
+			PackageFragment pkg = (PackageFragment) getParent();
+			JarPackageFragmentRoot jarRoot = (JarPackageFragmentRoot) getPackageFragmentRoot();
+			String entryName = jarRoot.getClassFilePath(Util.concatWith(pkg.names, getElementName(), '/'));
+			byte[] contents = getClassFileContent(jarRoot, entryName);
+			if (contents != null) {
+				String fileName;
+				String rootPath = root.getPath().toOSString();
+				if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) {
+					fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + 
+							root.getElementName() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
+				} else {
+					fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
+				}
+				result = new ClassFileReader(contents, fileName.toCharArray(), false);
+			}
+		} else {
+			result = BinaryTypeFactory.readType(descriptor, null);
+		}
+	} else {
+		result = BinaryTypeFactory.readType(descriptor, null);
+	}
+		
 	if (result == null) {
 		return null;
 	}
 
 	// TODO(sxenos): setup the external annotation provider if the IBinaryType came from the index
-	PackageFragment pkg = (PackageFragment) getParent();
-	IJavaElement grandparent = pkg.getParent();
-	if (grandparent instanceof JarPackageFragmentRoot) {
-		JarPackageFragmentRoot root = (JarPackageFragmentRoot) grandparent;
-
-		if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
-			JavaProject javaProject = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT);
-			IClasspathEntry entry = javaProject.getClasspathEntryFor(getPath());
-			if (entry != null) {
-				String entryName = new String(CharArrayUtils.concat(
-						JavaNames.fieldDescriptorToBinaryName(descriptor.fieldDescriptor), SuffixConstants.SUFFIX_CLASS));
-				IProject project = javaProject.getProject();
-				IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project, false); // unresolved for use in ExternalAnnotationTracker
-				if (externalAnnotationPath != null) {
-					result = setupExternalAnnotationProvider(project, externalAnnotationPath, result, 
+	if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
+		JavaProject javaProject = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT);
+		IClasspathEntry entry = javaProject.getClasspathEntryFor(getPath());
+		if (entry != null) {
+			PackageFragment pkg = (PackageFragment) getParent();
+			String entryName = Util.concatWith(pkg.names, getElementName(), '/');
+			entryName = new String(CharArrayUtils.concat(
+					JavaNames.fieldDescriptorToBinaryName(descriptor.fieldDescriptor), SuffixConstants.SUFFIX_CLASS));
+			IProject project = javaProject.getProject();
+			IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project, false); // unresolved for use in ExternalAnnotationTracker
+			if (externalAnnotationPath != null) {
+				result = setupExternalAnnotationProvider(project, externalAnnotationPath, result, 
 						entryName.substring(0, entryName.length() - SuffixConstants.SUFFIX_CLASS.length));
-				} else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
-					result = new ExternalAnnotationDecorator(result, true);
-				}
+			} else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+				result = new ExternalAnnotationDecorator(result, true);
 			}
 		}
 	}
@@ -466,7 +515,7 @@
 		case IJavaModelStatusConstants.INVALID_ELEMENT_TYPES: // don't throw a JavaModelException to be able to open .class file in proj==src case without source (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=221904 )
 			return null;
 		default:
-			throw new JavaModelException((IJavaModelStatus) status);
+			throw new JavaModelException(status);
 		}
 	}
 }
@@ -582,6 +631,11 @@
 			String typeName = memento.nextToken();
 			JavaElement type = new BinaryType(this, typeName);
 			return type.getHandleFromMemento(memento, owner);
+		case JEM_MODULE:
+			if (!memento.hasMoreTokens()) return this;
+			String modName = memento.nextToken();
+			JavaElement mod = new BinaryModule(this, modName);
+			return mod.getHandleFromMemento(memento, owner);
 	}
 	return null;
 }
@@ -948,4 +1002,9 @@
 public ISourceRange getNameRange() {
 	return null;
 }
+
+@Override
+public IModuleDescription getModule() throws JavaModelException {
+	return ((ClassFileInfo)getElementInfo()).getModule();
+}
 }
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 094ddca..d51f590 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -15,12 +19,15 @@
 
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 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.IModule;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -152,6 +159,9 @@
 	if ((tagBits & TagBits.AnnotationForTypeParameter) != 0) {
 		values.add(elementType + new String(TypeConstants.TYPE_PARAMETER_TARGET));
 	}
+	if ((tagBits & TagBits.AnnotationForModule) != 0) {
+		values.add(elementType + new String(TypeConstants.UPPER_MODULE));
+	}
 	final Object value;
 	if (values.size() == 0) {
 		if ((tagBits & TagBits.AnnotationTarget) != 0)
@@ -246,6 +256,17 @@
 		}
 	}
 }
+private void generateModuleInfos(ClassFile classFile, IBinaryType info, HashMap newElements, ArrayList childrenHandles) {
+	// TODO: The following needs fix once we can get ModuleDeclaration from IndexBinaryType
+	IModule modDecl = (info instanceof ClassFileReader) ? ((ClassFileReader) info).getModuleDeclaration() : null;
+	if (modDecl != null) {
+		char[] modName = modDecl.name();
+		BinaryModule handle = new BinaryModule(classFile, new String(modName));
+		ModuleDescriptionInfo moduleInfo = ModuleDescriptionInfo.createModule(modDecl);
+		setModule(handle);
+		newElements.put(handle, moduleInfo);
+	}
+}
 /**
  * Creates the handles and infos for the methods of the given binary type.
  * Adds new handles to the given vector.
@@ -426,6 +447,9 @@
 		generateFieldInfos(type, typeInfo, newElements, childrenHandles);
 		generateMethodInfos(type, typeInfo, newElements, childrenHandles, typeParameterHandles);
 		generateInnerClassHandles(type, typeInfo, childrenHandles); // Note inner class are separate openables that are not opened here: no need to pass in newElements
+		if (TypeDeclaration.kind(typeInfo.getModifiers()) == TypeDeclaration.MODULE_DECL) {
+			generateModuleInfos(classFile, typeInfo, newElements, childrenHandles);
+		}
 	}
 
 	this.binaryChildren = new JavaElement[childrenHandles.size()];
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
index 7d1df25..c23fae8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -136,6 +140,10 @@
 							continue; // null and not-null
 						}						
 					}
+					if (((ClasspathEntry) entry).isAutomaticModule() !=
+							((ClasspathEntry) other).isAutomaticModule()) {
+						continue nextEntry;
+					}
 					return i;
 			}
 		}
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 c69d88f..e3e7414 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
@@ -4,7 +4,11 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- *
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
@@ -1434,6 +1438,14 @@
 		}
 		return false;
 	}
+	public boolean isAutomaticModule() {
+		for (int i = 0, length = this.extraAttributes.length; i < length; i++) {
+			IClasspathAttribute attribute = this.extraAttributes[i];
+			if (IClasspathAttribute.AUTOMATIC_MODULE.equals(attribute.getName()) && "true".equals(attribute.getValue())) //$NON-NLS-1$
+				return true;
+		}
+		return false;
+	}
 
 	public String getSourceAttachmentEncoding() {
 		for (int i = 0, length = this.extraAttributes.length; i < length; i++) {
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 c7d5974..fdfb9ad 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Alex Smirnoff (alexsmr@sympatico.ca) - part of the changes to support Java-like extension
@@ -24,6 +28,7 @@
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -742,6 +747,11 @@
 			String typeName = memento.nextToken();
 			JavaElement type = (JavaElement)getType(typeName);
 			return type.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_MODULE:
+			if (!memento.hasMoreTokens()) return this;
+			String modName = memento.nextToken();
+			JavaElement mod = new SourceModule(this, modName);
+			return mod.getHandleFromMemento(memento, workingCopyOwner);
 	}
 	return null;
 }
@@ -1353,4 +1363,24 @@
 public ISourceRange getNameRange() {
 	return null;
 }
+
+
+@Override
+public IModuleDescription getModule() throws JavaModelException {
+	if (TypeConstants.MODULE_INFO_FILE_NAME_STRING.equals(getElementName()))
+		return ((CompilationUnitElementInfo) getElementInfo()).getModule();
+	JavaProject project = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT);
+	return project.getModuleDescription();
+}
+public char[] module() {
+	try {
+		IModuleDescription module = getModule();
+		if (module != null)
+			return module.getElementName().toCharArray();
+	} catch (JavaModelException e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index 34b4ca9..fa18b9c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -23,6 +27,7 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMemberValuePair;
 import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -253,6 +258,10 @@
 	String nameString= new String(typeInfo.name);
 	return new SourceType(parent, nameString);
 }
+protected SourceModule createModuleHandle(JavaElement parent, ModuleInfo modInfo) {
+	String nameString= new String(modInfo.moduleName);
+	return new org.eclipse.jdt.internal.core.SourceModule(parent, nameString);
+}
 protected TypeParameter createTypeParameter(JavaElement parent, String name) {
 	return new TypeParameter(parent, name);
 }
@@ -491,7 +500,17 @@
 	}
 	return result;
 }
+public void enterModule(ModuleInfo info) {
 
+	Object parentInfo = this.infoStack.peek();
+	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
+	JavaElement handle = createModuleHandle(parentHandle, info);
+	
+	this.infoStack.push(info);
+	this.handleStack.push(handle);
+
+	addToChildren(parentInfo, handle);
+}
 /**
  * @see ISourceElementRequestor
  */
@@ -499,9 +518,9 @@
 
 	Object parentInfo = this.infoStack.peek();
 	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
-	SourceType handle = createTypeHandle(parentHandle, typeInfo); //NB: occurenceCount is computed in resolveDuplicates
-	resolveDuplicates(handle);
-
+	JavaElement handle = createTypeHandle(parentHandle, typeInfo);
+	 //NB: occurenceCount is computed in resolveDuplicates
+	resolveDuplicates((SourceType) handle);
 	this.infoStack.push(typeInfo);
 	this.handleStack.push(handle);
 
@@ -509,6 +528,17 @@
 		((TypeInfo) parentInfo).childrenCategories.put(handle, typeInfo.categories);
 	addToChildren(parentInfo, handle);
 }
+private org.eclipse.jdt.internal.core.ModuleDescriptionInfo createModuleInfo(ModuleInfo modInfo, org.eclipse.jdt.internal.core.SourceModule handle) {
+	org.eclipse.jdt.internal.core.ModuleDescriptionInfo info = org.eclipse.jdt.internal.core.ModuleDescriptionInfo.createModule(modInfo.node);
+	info.setHandle(handle);
+	info.setSourceRangeStart(modInfo.declarationStart);
+	info.setFlags(modInfo.modifiers);
+	info.setNameSourceStart(modInfo.nameSourceStart);
+	info.setNameSourceEnd(modInfo.nameSourceEnd);
+	this.newElements.put(handle, info);
+
+	return info;
+}
 private SourceTypeElementInfo createTypeInfo(TypeInfo typeInfo, SourceType handle) {
 	SourceTypeElementInfo info =
 		typeInfo.anonymousMember ?
@@ -702,16 +732,34 @@
 	this.handleStack.pop();
 	this.infoStack.pop();
 }
+public void exitModule(int declarationEnd) {
+	ModuleInfo moduleInfo = (ModuleInfo) this.infoStack.peek();
+	SourceModule handle = (SourceModule) this.handleStack.peek();
+	JavaProject proj = (JavaProject) handle.getAncestor(IJavaElement.JAVA_PROJECT);
+	if (proj != null) {
+		try {
+			org.eclipse.jdt.internal.core.SourceModule moduleDecl = handle;
+			org.eclipse.jdt.internal.core.ModuleDescriptionInfo info = createModuleInfo(moduleInfo, moduleDecl);
+			info.setSourceRangeEnd(declarationEnd);
+			info.children = getChildren(info);
+			this.unitInfo.setModule(moduleDecl);
+			proj.setModuleDescription(moduleDecl);
+		} catch (JavaModelException e) {
+			// Unexpected while creating
+		}
+	}
+	this.handleStack.pop();
+	this.infoStack.pop();
+}
 /**
  * @see ISourceElementRequestor
  */
 public void exitType(int declarationEnd) {
-	SourceType handle = (SourceType) this.handleStack.peek();
 	TypeInfo typeInfo = (TypeInfo) this.infoStack.peek();
+	SourceType handle = (SourceType) this.handleStack.peek();
 	SourceTypeElementInfo info = createTypeInfo(typeInfo, handle);
 	info.setSourceRangeEnd(declarationEnd);
 	info.children = getChildren(typeInfo);
-	
 	this.handleStack.pop();
 	this.infoStack.pop();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
index 1b7c9ec..fb9a39b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -87,7 +87,7 @@
 		initializeASTParser();
 	}
 	private void initializeASTParser() {
-		this.parser = ASTParser.newParser(AST.JLS8);
+		this.parser = ASTParser.newParser(AST.JLS9);
 	}
 	/**
 	 * Returns the children of <code>source</code> which are affected by this operation.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
index cbb38db..199fbfa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -261,7 +261,7 @@
 		// ensure cu is consistent (noop if already consistent)
 		cu.makeConsistent(this.progressMonitor);
 		// create an AST for the compilation unit
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setSource(cu);
 		return (CompilationUnit) parser.createAST(this.progressMonitor);
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
index d1e230e..48a4e25 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -78,7 +78,7 @@
 protected ASTNode generateElementAST(ASTRewrite rewriter, ICompilationUnit cu) throws JavaModelException {
 	if (this.createdNode == null) {
 		this.source = removeIndentAndNewLines(this.source, cu);
-		ASTParser parser = ASTParser.newParser(AST.JLS8);
+		ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setSource(this.source.toCharArray());
 		parser.setProject(getCompilationUnit().getJavaProject());
 		parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
@@ -165,7 +165,7 @@
 	buff.append(lineSeparator + " public class A {" + lineSeparator); //$NON-NLS-1$
 	buff.append(this.source);
 	buff.append(lineSeparator).append('}');
-	ASTParser parser = ASTParser.newParser(AST.JLS8);
+	ASTParser parser = ASTParser.newParser(AST.JLS9);
 	parser.setSource(buff.toString().toCharArray());
 	CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null);
 	TypeDeclaration typeDeclaration = (TypeDeclaration) compilationUnit.types().iterator().next();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
index 593a890..0bc605c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -81,7 +81,7 @@
 	}
 
 	private void initASTParser() {
-		this.parser = ASTParser.newParser(AST.JLS8);
+		this.parser = ASTParser.newParser(AST.JLS9);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 34a9211..ba1ff97 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -34,6 +34,7 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
 import org.eclipse.jdt.internal.core.builder.JavaBuilder;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
@@ -552,6 +553,28 @@
 					javaProject = (JavaProject)JavaCore.create(file.getProject());
 					javaProject.resetResolvedClasspath();
 					this.state.rootsAreStale = true;
+				} else if (file.getName().toLowerCase().contains(new String(TypeConstants.MODULE_INFO_FILE_NAME))) {
+					switch(kind) {
+						case IResourceDelta.CHANGED :
+							int flags = delta.getFlags();
+							if ((flags & IResourceDelta.CONTENT) == 0)
+								break;
+							javaProject = (JavaProject)JavaCore.create(file.getProject());
+							this.manager.removePerProjectInfo(javaProject, false);
+							this.state.rootsAreStale = true;
+							break;
+							//$FALL-THROUGH$
+						case IResourceDelta.ADDED :
+						case IResourceDelta.REMOVED :
+							javaProject = (JavaProject)JavaCore.create(file.getProject());
+							try {
+								// Make sure module description is read
+								javaProject.close();
+							} catch (JavaModelException e) {
+								// do nothing
+							}
+							break;
+					}
 				}
 				break;
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
index f054045..8a0ddad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 
@@ -30,6 +31,7 @@
 public void acceptMethod(IMethod method);
 public void acceptPackageFragment(IPackageFragment packageFragment);
 public void acceptType(IType type);
+public void acceptModule(IModuleDescription module);
 /**
  * Returns <code>true</code> if this IJavaElementRequestor does
  * not want to receive any more results.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java
new file mode 100644
index 0000000..26d1609
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JModPackageFragmentRoot.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.builder.ClasspathJMod;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
+
+/**
+ * A package fragment root that corresponds to a JMod file.
+ *
+ * <p>NOTE: The only visible entries from a Jmod package fragment root
+ * are .class files. The sub folder "classes" where the .class files are nested under
+ * is hidden from clients. THe package fragments appear to be directly under the 
+ * package fragment roots.
+ * <p>NOTE: A JMod package fragment root may or may not have an associated resource.
+ *
+ * @see org.eclipse.jdt.core.IPackageFragmentRoot
+ * @see org.eclipse.jdt.internal.core.JarPackageFragmentRootInfo
+ */
+public class JModPackageFragmentRoot extends JarPackageFragmentRoot {
+
+	/**
+	 * Constructs a package fragment root which is the root of the Java package directory hierarchy
+	 * based on a JMOD file that is not contained in a <code>IJavaProject</code> and
+	 * does not have an associated <code>IResource</code>.
+	 */
+	protected JModPackageFragmentRoot(IPath externalPath, JavaProject project) {
+		super(externalPath, project);
+	}
+	/**
+	 * Constructs a package fragment root which is the root of the Java package directory hierarchy
+	 * based on a JMOD file.
+	 */
+	protected JModPackageFragmentRoot(IResource resource, JavaProject project) {
+		super(resource, project);
+	}
+
+	/**
+	 * @see PackageFragmentRoot#getClassFilePath(String)
+	 */
+	public String getClassFilePath(String entryName) {
+		char[] name = CharOperation.append(ClasspathJMod.CLASSES_FOLDER, entryName.toCharArray());
+		return new String(name);
+	}
+	protected void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) {
+		char[] name = entryName.toCharArray();
+		if (CharOperation.prefixEquals(ClasspathJMod.CLASSES_FOLDER, name)) {
+			name = CharOperation.subarray(name, ClasspathJMod.CLASSES_FOLDER.length, name.length);
+		}
+		super.initRawPackageInfo(rawPackageInfo, new String(name), isDirectory, compliance);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java
index cb04892..de0657c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
index 21af1eb..62669aa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
@@ -1,16 +1,21 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.zip.ZipEntry;
@@ -18,9 +23,12 @@
 
 import org.eclipse.core.resources.IStorage;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IJarEntryResource;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 /**
@@ -30,7 +38,6 @@
  */
 public class JarEntryFile  extends JarEntryResource {
 	private static final IJarEntryResource[] NO_CHILDREN = new IJarEntryResource[0];
-
 	public JarEntryFile(String simpleName) {
 		super(simpleName);
 	}
@@ -42,24 +49,38 @@
 	}
 
 	public InputStream getContents() throws CoreException {
-		ZipFile zipFile = null;
-		try {
-			zipFile = getZipFile();
-			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
-				System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " +zipFile.getName()); //$NON-NLS-1$	//$NON-NLS-2$
+		IPackageFragmentRoot root = getPackageFragmentRoot();
+		if (Util.isJrt(root.getPath().toOSString())) {
+			try {
+				IPath rootPath = root.getPath();
+				Object target = JavaModel.getTarget(rootPath, false);
+				if (target != null && target instanceof File) {
+					return JRTUtil.getContentFromJrt((File) target, getEntryName(), root.getElementName());
+				}
+			} catch (IOException e) {
+				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
 			}
-			String entryName = getEntryName();
-			ZipEntry zipEntry = zipFile.getEntry(entryName);
-			if (zipEntry == null){
-				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, entryName));
+			return null;
+		} else {
+			ZipFile zipFile = null;
+			try {
+				zipFile = getZipFile();
+				if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
+					System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " +zipFile.getName()); //$NON-NLS-1$	//$NON-NLS-2$
+				}
+				String entryName = getEntryName();
+				ZipEntry zipEntry = zipFile.getEntry(entryName);
+				if (zipEntry == null){
+					throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, entryName));
+				}
+				byte[] contents = Util.getZipEntryByteContent(zipEntry, zipFile);
+				return new ByteArrayInputStream(contents);
+			} catch (IOException e){
+				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+			} finally {
+				// avoid leaking ZipFiles
+				JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
 			}
-			byte[] contents = Util.getZipEntryByteContent(zipEntry, zipFile);
-			return new ByteArrayInputStream(contents);
-		} catch (IOException e){
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-		} finally {
-			// avoid leaking ZipFiles
-			JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java
index 57a2775..50773f6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
index f9675fd..8d78557 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -48,7 +52,7 @@
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class JarPackageFragmentRoot extends PackageFragmentRoot {
 
-	private final static ArrayList EMPTY_LIST = new ArrayList();
+	protected final static ArrayList EMPTY_LIST = new ArrayList();
 
 	/**
 	 * The path to the jar file
@@ -81,7 +85,7 @@
 	 * by the path of class files contained in the jar of this package fragment root.
 	 */
 	protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException {
-		HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject();
+		final HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject();
 		IJavaElement[] children;
 		try {
 			// always create the default package
@@ -132,7 +136,6 @@
 					JavaModelManager.getJavaModelManager().closeZipFile(jar);
 				}
 			}
-
 			// loop through all of referenced packages, creating package fragments if necessary
 			// and cache the entry names in the rawPackageInfo table
 			children = new IJavaElement[rawPackageInfo.size()];
@@ -158,6 +161,19 @@
 		((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo;
 		return true;
 	}
+	protected IJavaElement[] createChildren(final HashtableOfArrayToObject rawPackageInfo) {
+		IJavaElement[] children;
+		// loop through all of referenced packages, creating package fragments if necessary
+		// and cache the entry names in the rawPackageInfo table
+		children = new IJavaElement[rawPackageInfo.size()];
+		int index = 0;
+		for (int i = 0, length = rawPackageInfo.keyTable.length; i < length; i++) {
+			String[] pkgName = (String[]) rawPackageInfo.keyTable[i];
+			if (pkgName == null) continue;
+			children[index++] = getPackageFragment(pkgName);
+		}
+		return children;
+	}
 	/**
 	 * Returns a new element info for this element.
 	 */
@@ -225,6 +241,9 @@
 	public PackageFragment getPackageFragment(String[] pkgName) {
 		return new JarPackageFragment(this, pkgName);
 	}
+	public PackageFragment getPackageFragment(String[] pkgName, String mod) {
+		return new JarPackageFragment(this, pkgName); // Overridden in JImageModuleFragmentBridge
+	}
 	public IPath internalPath() {
 		if (isExternal()) {
 			return this.jarPath;
@@ -255,8 +274,17 @@
 	public int hashCode() {
 		return this.jarPath.hashCode();
 	}
-	private void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) {
-		int lastSeparator = isDirectory ? entryName.length()-1 : entryName.lastIndexOf('/');
+	protected void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String compliance) {
+		int lastSeparator;
+		if (isDirectory) {
+			if (entryName.charAt(entryName.length() - 1) == '/') {
+				lastSeparator = entryName.length() - 1;
+			} else {
+				lastSeparator = entryName.length();
+			}
+		} else {
+			lastSeparator = entryName.lastIndexOf('/');
+		}
 		String[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator);
 		String[] existing = null;
 		int length = pkgName.length;
@@ -316,7 +344,6 @@
 	public boolean isReadOnly() {
 		return true;
 	}
-
 	/**
 	 * Returns whether the corresponding resource or associated file exists
 	 */
@@ -348,5 +375,12 @@
 		}
 		return null;
 	}
-
+//	@Override
+//	public boolean isModule() {
+//	 	try {
+//	 		return ((PackageFragmentRootInfo) getElementInfo()).isModule(resource(), this);
+//	 	} catch (JavaModelException e) {
+//	 		return false;
+//	 	}
+//	}
 }
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 67f3e53..9630b03 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
@@ -96,6 +96,7 @@
 	public static final char JEM_LAMBDA_EXPRESSION = ')';
 	public static final char JEM_LAMBDA_METHOD = '&';
 	public static final char JEM_STRING = '"';
+	public static final char JEM_MODULE = '`';
 	
 	/**
 	 * Before ')', '&' and '"' became the newest additions as delimiters, the former two
@@ -120,6 +121,7 @@
 	 */
 	protected JavaElement parent;
 
+	protected static final String[] NO_STRINGS = new String[0];
 	protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0];
 	protected static final Object NO_INFO = new Object();
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
index 86b94bf..70ec0f8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 
@@ -67,6 +68,12 @@
 	protected ArrayList types= null;
 
 	/**
+	 * A collection of the resulting modules, or <code>null</code>
+	 * if no module results have been received
+	 */
+	protected ArrayList modules = null;
+
+	/**
 	 * Empty arrays used for efficiency
 	 */
 	protected static final IField[] EMPTY_FIELD_ARRAY= new IField[0];
@@ -74,6 +81,7 @@
 	protected static final IType[] EMPTY_TYPE_ARRAY= new IType[0];
 	protected static final IPackageFragment[] EMPTY_PACKAGE_FRAGMENT_ARRAY= new IPackageFragment[0];
 	protected static final IMethod[] EMPTY_METHOD_ARRAY= new IMethod[0];
+	protected static final IModuleDescription[] EMPTY_MODULE_ARRAY= new IModuleDescription[0];
 /**
  * @see IJavaElementRequestor
  */
@@ -131,6 +139,16 @@
 /**
  * @see IJavaElementRequestor
  */
+public void acceptModule(IModuleDescription module) {
+	if (this.modules == null) {
+		this.modules= new ArrayList();
+	}
+	this.modules.add(module);	
+}
+
+/**
+ * @see IJavaElementRequestor
+ */
 public IField[] getFields() {
 	if (this.fields == null) {
 		return EMPTY_FIELD_ARRAY;
@@ -203,6 +221,18 @@
 /**
  * @see IJavaElementRequestor
  */
+public IModuleDescription[] getModules() {
+	if (this.modules == null) {
+		return EMPTY_MODULE_ARRAY;
+	}
+	int size = this.modules.size();
+	IModuleDescription[] results = new IModuleDescription[size];
+	this.modules.toArray(results);
+	return results;
+}
+/**
+ * @see IJavaElementRequestor
+ */
 public boolean isCanceled() {
 	return this.canceled;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
index 8e8a746..881fdd4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
@@ -27,6 +31,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Messages;
 
@@ -361,6 +366,17 @@
 	return false;
 }
 
+public static boolean isJimage(File file) {
+	return JavaModelManager.isJrt(file.getPath());
+}
+public static boolean isJmod(File file) {
+	IPath path = Path.fromOSString(file.getPath());
+	if (path.getFileExtension().equalsIgnoreCase(SuffixConstants.EXTENSION_jmod)) {
+		return true;
+	}
+	return false;
+}
+
 /**
  * Returns whether the provided path is an external file, checking and updating the
  * JavaModelManager's external file cache.
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 5aaa78f..757abde 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Theodora Yeung (tyeung@bea.com) - ensure that JarPackageFragmentRoot make it into cache
@@ -125,6 +129,8 @@
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
 import org.eclipse.jdt.internal.core.builder.JavaBuilder;
 import org.eclipse.jdt.internal.core.dom.SourceRangeVerifier;
@@ -410,7 +416,7 @@
 
 	public static class CompilationParticipants {
 
-		private final static int MAX_SOURCE_LEVEL = 8; // 1.1 to 1.8
+		private final static int MAX_SOURCE_LEVEL = 9; // 1.1 to 1.8 and 9
 
 		/*
 		 * The registered compilation participants (a table from int (source level) to Object[])
@@ -536,6 +542,8 @@
 		 * ...
 		 * 1.6 -> 5
 		 * 1.7 -> 6
+		 * 1.8 -> 7
+		 * 9 -> 8
 		 * null -> 0
 		 */
 		private int indexForSourceLevel(String sourceLevel) {
@@ -556,6 +564,8 @@
 					return 6;
 				case ClassFileConstants.MAJOR_VERSION_1_8:
 					return 7;
+				case ClassFileConstants.MAJOR_VERSION_9:
+					return 8;
 				default:
 					// all other cases including ClassFileConstants.MAJOR_VERSION_1_1
 					return 0;
@@ -1245,6 +1255,7 @@
 		public Map rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry
 		public Map rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry
 		public IPath outputLocation;
+		public Map<IPath, ObjectVector> jrtRoots; // A map between a JRT file system (as a string) and the package fragment roots found in it.
 
 		public IEclipsePreferences preferences;
 		public Hashtable options;
@@ -1364,6 +1375,11 @@
 			return setClasspath(this.rawClasspath, referencedEntries, this.outputLocation, this.rawClasspathStatus, newResolvedClasspath, newRootPathToRawEntries, newRootPathToResolvedEntries, newUnresolvedEntryStatus, addClasspathChange);
 		}
 
+		public synchronized void setJrtPackageRoots(IPath jrtPath, ObjectVector roots) {
+			if (this.jrtRoots == null) this.jrtRoots = new HashMap<>();
+			this.jrtRoots.put(jrtPath, roots);
+		}
+
 		/**
 		 * Reads the classpath and caches the entries. Returns a two-dimensional array, where the number of elements in the row is fixed to 2.
 		 * The first element is an array of raw classpath entries and the second element is an array of referenced entries that may have been stored
@@ -1548,6 +1564,7 @@
 	public static boolean CP_RESOLVE_VERBOSE_ADVANCED = false;
 	public static boolean CP_RESOLVE_VERBOSE_FAILURE = false;
 	public static boolean ZIP_ACCESS_VERBOSE = false;
+	public static boolean JRT_ACCESS_VERBOSE = false;
 	
 	/**
 	 * A cache of opened zip files per thread.
@@ -1556,7 +1573,8 @@
 	private ThreadLocal zipFiles = new ThreadLocal();
 
 	private UserLibraryManager userLibraryManager;
-	
+
+	private ModuleSourcePathManager modulePathManager;
 	/*
 	 * A set of IPaths for jars that are known to not contain a chaining (through MANIFEST.MF) to another library
 	 */
@@ -2724,6 +2742,17 @@
 		return MANAGER.userLibraryManager;
 	}
 
+	public static ModuleSourcePathManager getModulePathManager() {
+		if (MANAGER.modulePathManager == null) {
+			ModuleSourcePathManager modulePathManager = new ModuleSourcePathManager();
+			synchronized(MANAGER) {
+				if (MANAGER.modulePathManager == null) { // ensure another library manager was not set while creating the instance above
+					MANAGER.modulePathManager = modulePathManager;
+				}
+			}
+		}
+		return MANAGER.modulePathManager;
+	}
 	/*
 	 * Returns all the working copies which have the given owner.
 	 * Adds the working copies of the primary owner if specified.
@@ -2765,7 +2794,19 @@
 		return this.workspaceScope;
 	}
 
+	public static boolean isJrt(IPath path) {
+		return path.toString().endsWith(JRTUtil.JRT_FS_JAR);
+	}
+
+	public static boolean isJrt(String path) {
+		return isJrt(new Path(path));
+	}
+
 	public void verifyArchiveContent(IPath path) throws CoreException {
+		// TODO: we haven't finalized what path the JRT is represented by. Don't attempt to validate it.
+		if (isJrt(path)) {
+			return;
+		}
 		throwExceptionIfArchiveInvalid(path);
 		// Check if we can determine the archive's validity by examining the index
 		if (JavaIndex.isEnabled()) {
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 e687309..3fe2dba 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
@@ -15,6 +19,8 @@
 
 import java.io.*;
 import java.net.URI;
+import java.nio.file.FileVisitResult;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -47,6 +53,7 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.content.IContentDescription;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.core.runtime.preferences.IScopeContext;
@@ -59,6 +66,7 @@
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IRegion;
@@ -70,6 +78,11 @@
 import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.eval.IEvaluationContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
@@ -109,7 +122,7 @@
 @SuppressWarnings({ "rawtypes", "unchecked" })
 public class JavaProject
 	extends Openable
-	implements IJavaProject, IProjectNature, SuffixConstants {
+	implements IJavaProject, IProjectNature, IModuleEnvironment, SuffixConstants {
 
 	/**
 	 * Name of file containing project classpath
@@ -458,8 +471,25 @@
 		IClasspathEntry[] resolvedClasspath = getResolvedClasspath();
 
 		// compute the pkg fragment roots
-		info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/));
-
+		IPackageFragmentRoot[] roots = computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/);
+		info.setChildren(roots);
+		IModuleDescription module = null;
+		IModuleDescription current = null;
+		for (IPackageFragmentRoot root : roots) {
+			if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
+				continue;
+			module = root.getModuleDescription();
+			if (module != null) {
+				if (current != null) {
+					throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, 
+							Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName())));
+				}
+				current = module;
+				JavaModelManager.getModulePathManager().addEntry(module, this);
+				//break; continue looking, there may be other roots containing module-info
+				info.setModule(module);
+			}
+		}
 		return true;
 	}
 
@@ -610,7 +640,23 @@
 				} else if (target instanceof File) {
 					// external target
 					if (JavaModel.isFile(target)) {
-						root = new JarPackageFragmentRoot(entryPath, this);
+						if (JavaModel.isJimage((File) target)) {
+							PerProjectInfo info = getPerProjectInfo();
+							if (info.jrtRoots == null || !info.jrtRoots.containsKey(entryPath)) {
+								ObjectVector imageRoots = new ObjectVector();
+								loadModulesInJimage(entryPath, imageRoots, rootToResolvedEntries, resolvedEntry, referringEntry);
+								info.setJrtPackageRoots(entryPath, imageRoots);
+								accumulatedRoots.addAll(imageRoots);
+								rootIDs.add(rootID);
+							} else {
+								accumulatedRoots.addAll(info.jrtRoots.get(entryPath));
+							}
+						} else if (JavaModel.isJmod((File) target)) {
+							root = new JModPackageFragmentRoot(entryPath, this);
+						}
+						else {
+							root = new JarPackageFragmentRoot(entryPath, this);
+						}
 					} else if (((File) target).isDirectory()) {
 						root = new ExternalPackageFragmentRoot(entryPath, this);
 					}
@@ -648,6 +694,63 @@
 	}
 
 	/**
+	 * This bogus package fragment root acts as placeholder plus bridge for the
+	 * real one until the module name becomes available. It is useful in certain
+	 * scenarios like creating package roots from delta processors, search etc.
+	 */
+	class JImageModuleFragmentBridge extends JarPackageFragmentRoot {
+
+		protected JImageModuleFragmentBridge(IPath externalJarPath) {
+			super(externalJarPath, JavaProject.this);
+		}
+		public PackageFragment getPackageFragment(String[] pkgName) {
+			return getPackageFragment(pkgName, null);
+		}
+		public PackageFragment getPackageFragment(String[] pkgName, String mod) {
+			PackageFragmentRoot realRoot = new JrtPackageFragmentRoot(this.jarPath,
+												mod == null ?  JRTUtil.JAVA_BASE : mod,
+														JavaProject.this);
+			return new JarPackageFragment(realRoot, pkgName);
+		}
+		protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException {
+			// Do nothing, idea is to avoid this being read in JarPackageFragmentRoot as a Jar.
+			return true;
+		}
+		public boolean isModule() {
+			return true;
+		}
+	}
+
+	private void loadModulesInJimage(final IPath imagePath, final ObjectVector roots, final Map rootToResolvedEntries, 
+				final IClasspathEntry resolvedEntry, final IClasspathEntry referringEntry) {
+		try {
+			org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imagePath.toFile(),
+					new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<java.nio.file.Path>() {
+				@Override
+				public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+					return FileVisitResult.SKIP_SIBLINGS;
+				}
+
+				@Override
+				public FileVisitResult visitFile(java.nio.file.Path path, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+					return FileVisitResult.SKIP_SIBLINGS;
+				}
+
+				@Override
+				public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException {
+					JrtPackageFragmentRoot root = new JrtPackageFragmentRoot(imagePath, mod.toString(), JavaProject.this);
+					roots.add(root);
+					if (rootToResolvedEntries != null) 
+						rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry));
+					return FileVisitResult.SKIP_SUBTREE;
+				}
+			}, JRTUtil.NOTIFY_MODULES);
+		} catch (IOException e) {
+			Util.log(IStatus.ERROR, "Error reading modules from " + imagePath.toOSString()); //$NON-NLS-1$
+		}
+	}
+
+	/**
 	 * Returns (local/all) the package fragment roots identified by the given project's classpath.
 	 * Note: this follows project classpath references to find required project contributions,
 	 * eliminating duplicates silently.
@@ -1225,7 +1328,7 @@
 		}
 		for (int i= 0; i < allRoots.length; i++) {
 			IPackageFragmentRoot classpathRoot= allRoots[i];
-			if (classpathRoot.getPath().equals(path)) {
+			if (classpathRoot.getPath() != null && classpathRoot.getPath().equals(path)) {
 				return classpathRoot;
 			}
 		}
@@ -1582,6 +1685,7 @@
 	 * @see JavaElement
 	 */
 	public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
+		String mod = null;
 		switch (token.charAt(0)) {
 			case JEM_PACKAGEFRAGMENTROOT:
 				String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
@@ -1591,11 +1695,22 @@
 					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821
 					if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) {
 						break;
+					} else if (token == MementoTokenizer.PACKAGEFRAGMENTROOT) {
+						if (memento.hasMoreTokens()) {
+							token = memento.nextToken();
+							if (token != null) {
+								mod = token;
+							
+							}
+						}
+						continue;
 					}
 					rootPath += token;
 				}
-				JavaElement root = (JavaElement)getPackageFragmentRoot(new Path(rootPath));
-				if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
+				JavaElement root = (mod == null) ?
+						(JavaElement)getPackageFragmentRoot(new Path(rootPath)) :
+							new JrtPackageFragmentRoot(new Path(rootPath), mod, this);
+				if (token != null && (token.charAt(0) == JEM_PACKAGEFRAGMENT)) {
 					return root.getHandleFromMemento(token, memento, owner);
 				} else {
 					return root.getHandleFromMemento(memento, owner);
@@ -1827,6 +1942,15 @@
 		IFolder linkedFolder = JavaModelManager.getExternalManager().getFolder(externalLibraryPath);
 		if (linkedFolder != null)
 			return new ExternalPackageFragmentRoot(linkedFolder, externalLibraryPath, this);
+		if (JavaModelManager.isJrt(externalLibraryPath)) {
+			return this.new JImageModuleFragmentBridge(externalLibraryPath);
+		}
+		Object target = JavaModel.getTarget(externalLibraryPath, true/*check existency*/);
+		if (target instanceof File && JavaModel.isFile(target)) {
+			if (JavaModel.isJmod((File) target)) {
+				return new JModPackageFragmentRoot(externalLibraryPath, this);
+			}
+		}
 		return new JarPackageFragmentRoot(externalLibraryPath, this);
 	}
 
@@ -3232,4 +3356,33 @@
 		}
 		return JavaModelStatus.VERIFIED_OK;
 	}
+
+	public IModuleDescription getModuleDescription() throws JavaModelException {
+		JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo();
+		return info.getModule();
+	}
+
+	public void setModuleDescription(IModuleDescription module) throws JavaModelException {
+		JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo();	
+		IModuleDescription current = info.getModule();
+		if (current != null) {
+			IPackageFragmentRoot root = (IPackageFragmentRoot) current.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+			IPackageFragmentRoot newRoot = (IPackageFragmentRoot) module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+			if (!root.equals(newRoot))
+				throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
+						Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName())));
+		}
+		info.setModule(module);
+	}
+	@Override
+	public ITypeLookup typeLookup() {
+		// No direct way to lookup, use the java model APIs instead
+		return ITypeLookup.Dummy;
+	}
+
+	@Override
+	public IPackageLookup packageLookup() {
+		// No direct way to lookup, use the java model APIs instead
+		return IPackageLookup.Dummy;
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
index 21de2b3..115c060 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
@@ -255,7 +255,7 @@
 			return;
 		}
 		for (int j = 0, length = frags.length; j < length; j++) {
-			fragmentsCache.add(((PackageFragment) frags[j]).names);
+			if (frags[j] instanceof PackageFragment) fragmentsCache.add(((PackageFragment) frags[j]).names);
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java
new file mode 100644
index 0000000..ca732a7
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JrtPackageFragmentRoot.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * A package fragment root that corresponds to a module in a JRT file system.
+ *
+ * @see org.eclipse.jdt.core.IPackageFragmentRoot
+ * @see org.eclipse.jdt.internal.core.JarPackageFragmentRootInfo
+ */
+public class JrtPackageFragmentRoot extends JarPackageFragmentRoot implements IModulePathEntry, IModuleEnvironment {
+
+	String moduleName;
+	
+	/**
+	 * Constructs a package fragment root which represents a module
+	 * contained in a JRT.
+	 */
+	protected JrtPackageFragmentRoot(IPath jrtPath, String moduleName, JavaProject project) {
+		super(jrtPath, project);
+		this.moduleName = moduleName;
+	}
+
+	protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException {
+		final HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject();
+		final String compliance = CompilerOptions.VERSION_1_8; // TODO: BETA_JAVA9 Revisit
+
+		// always create the default package
+		rawPackageInfo.put(CharOperation.NO_STRINGS, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+
+		try {
+			org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(this.jarPath.toFile(),
+					new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+				@Override
+				public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) throws IOException {
+					initRawPackageInfo(rawPackageInfo, dir.toString(), true, compliance);
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitFile(Path path, Path mod, BasicFileAttributes attrs) throws IOException {
+					initRawPackageInfo(rawPackageInfo, path.toString(), false, compliance);
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitModule(Path mod) throws IOException {
+					if (!JrtPackageFragmentRoot.this.moduleName.equals(mod.toString())) {
+						return FileVisitResult.SKIP_SUBTREE;
+					}
+					return FileVisitResult.CONTINUE;
+				}
+			}, JRTUtil.NOTIFY_ALL);
+		} catch (IOException e) {
+			Util.log(IStatus.ERROR, "Error reading modules" + toStringWithAncestors()); //$NON-NLS-1$
+		}
+
+		info.setChildren(createChildren(rawPackageInfo));
+		((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo;
+		return true;
+	}
+	SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) throws JavaModelException {
+		IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath());
+		String encoding = (entry== null) ? null : ((ClasspathEntry) entry).getSourceAttachmentEncoding();
+		IModule mod = getModule();
+		String modName = mod == null ? null : new String(mod.name());
+		SourceMapper mapper = new SourceMapper(
+			sourcePath,
+			rootPath == null ? modName : rootPath.toOSString(),
+			getJavaProject().getOptions(true),// cannot use workspace options if external jar is 1.5 jar and workspace options are 1.4 options
+			encoding);
+		return mapper;
+	}
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (o instanceof JrtPackageFragmentRoot) {
+			JrtPackageFragmentRoot other= (JrtPackageFragmentRoot) o;
+			return this.moduleName.equals(other.moduleName) &&
+					this.jarPath.equals(other.jarPath);
+		}
+		return false;
+	}
+	public String getElementName() {
+		return this.moduleName;
+	}
+	public PackageFragment getPackageFragment(String[] pkgName) {
+		// NOTE: Do we need a different kind of package fragment?
+		return new JarPackageFragment(this, pkgName);
+	}
+	public int hashCode() {
+		return this.jarPath.hashCode() + this.moduleName.hashCode();
+	}
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
+		buffer.append(tabString(tab));
+		buffer.append("<module:").append(this.moduleName).append(">"); //$NON-NLS-1$ //$NON-NLS-2$
+		if (info == null) {
+			buffer.append(" (not open)"); //$NON-NLS-1$
+		}
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironment() {
+		// 
+		return this;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironmentFor(IModule module) {
+		// 
+		return getModule() == module ? this : null;
+	}
+
+	@Override
+	public ITypeLookup typeLookup() {
+		// No direct way to lookup, use the java model APIs instead
+		return ITypeLookup.Dummy;
+	}
+
+	@Override
+	public IPackageLookup packageLookup() {
+		// No direct way to lookup, use the java model APIs instead
+		return IPackageLookup.Dummy;
+	}
+
+	@Override
+	public IModule getModule() {
+		IModuleDescription desc = getModuleDescription();
+		if (desc != null) {
+			try {
+				return (ModuleDescriptionInfo)((JavaElement) desc).getElementInfo();
+			} catch (JavaModelException e) {
+				e.printStackTrace();
+			}
+		}
+		return null;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java
new file mode 100644
index 0000000..b1de2dc
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Module.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+//import org.eclipse.jdt.core.IType;
+//import org.eclipse.jdt.core.JavaModelException;
+//import org.eclipse.jdt.core.compiler.CharOperation;
+//import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+//import org.eclipse.jdt.internal.compiler.env.IModuleDeclaration;
+
+//public class Module implements org.eclipse.jdt.internal.compiler.env.IModuleDeclaration {
+//
+//	public ClassFile binaryDecl;
+//	public IModuleDeclaration declaration = null;
+//	public boolean isBinary = false;
+//	public SourceType sourceDecl;
+//
+//	public Module(SourceType sourceDecl) {
+//		this.sourceDecl = sourceDecl;
+//	}
+//	public Module(ClassFile binaryDecl) {
+//		this.binaryDecl = binaryDecl;
+//		this.isBinary = true;
+//	}
+//	@Override
+//	public char[] name() {
+//		//
+//		IModuleDeclaration decl = getDeclaration();
+//		return decl == null ? CharOperation.NO_CHAR : decl.name();
+//	}
+//	@Override
+//	public IModuleDeclaration getDeclaration() {
+//		// 
+//		if (this.declaration == null) {
+//			try {
+//				if (this.isBinary) {
+//					IType type = this.binaryDecl.getType();
+//					this.declaration = ((ClassFileReader) (((BinaryType)type).getElementInfo())).getModuleDeclaration();
+//				} else {
+//					this.declaration = (ModuleInfo) this.sourceDecl.getElementInfo();
+//				}
+//			}catch (JavaModelException e) {
+//				// do nothing
+//			}
+//		}
+//		return this.declaration;
+//	}
+//	
+//	public String toString() {
+//		return new String(this.name());
+//		
+//	}
+//}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java
new file mode 100644
index 0000000..99aec49
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleDescriptionInfo.java
@@ -0,0 +1,381 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+
+public class ModuleDescriptionInfo extends AnnotatableInfo implements IModule {
+
+	protected static final char[][] NO_USES = new char[0][0];
+	protected static final ModuleReferenceInfo[] NO_REQUIRES = new ModuleReferenceInfo[0];
+	protected static final PackageExportInfo[] NO_EXPORTS = new PackageExportInfo[0];
+	protected static final ServiceInfo[] NO_PROVIDES = new ServiceInfo[0];
+	protected static final PackageExportInfo[] NO_OPENS = new PackageExportInfo[0];
+
+	protected IJavaElement[] children = JavaElement.NO_ELEMENTS;
+
+	ModuleReferenceInfo[] requires;
+	PackageExportInfo[] exports;
+	ServiceInfo[] services;
+	PackageExportInfo[] opens;
+	char[][] usedServices;
+	IModuleDescription handle;
+	char[] name;
+
+	static class ModuleReferenceInfo extends MemberElementInfo implements IModule.IModuleReference {
+		char[] name;
+		int modifiers;
+		public char[] name() {
+			return this.name;
+		}
+		public int getModifiers() {
+			return this.modifiers;
+		}
+	}
+	static class PackageExportInfo extends MemberElementInfo implements IModule.IPackageExport {
+		char[] pack;
+		char[][] target;
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(this.pack);
+			if (this.target != null) {
+				buffer.append(" to "); //$NON-NLS-1$
+				for (char[] mod : this.target) {
+					buffer.append(mod);
+				}
+			}
+			buffer.append(';');
+			return buffer.toString();
+		}
+
+		@Override
+		public char[] name() {
+			return this.pack;
+		}
+
+		@Override
+		public char[][] targets() {
+			return this.target;
+		}
+	}
+
+	static class ServiceInfo extends MemberElementInfo implements IModule.IService {
+		char[] serviceName;
+		char[][] implNames;
+		@Override
+		public char[] name() {
+			return this.serviceName;
+		}
+		@Override
+		public char[][] with() {
+			return this.implNames;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(this.serviceName);
+			buffer.append(" with "); //$NON-NLS-1$
+			for (int i = 0; i < this.implNames.length; i++) {
+				buffer.append(this.implNames[i]);
+				if (i < this.implNames.length - 1)
+					buffer.append(", "); //$NON-NLS-1$
+			}
+			buffer.append(';');
+			return buffer.toString();
+		}
+	}
+	
+	public static ModuleDescriptionInfo createModule(IModule module) {
+		ModuleDescriptionInfo mod = new ModuleDescriptionInfo();
+		mod.name = module.name();
+		if (module.requires().length > 0) {
+			IModuleReference[] refs = module.requires();
+			mod.requires = new ModuleReferenceInfo[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				mod.requires[i] = new ModuleReferenceInfo();
+				mod.requires[i].name = refs[i].name(); // Check why ModuleReference#tokens must be a char[][] and not a char[] or String;
+				mod.requires[i].modifiers = refs[i].getModifiers();
+			}
+		} else {
+			mod.requires = NO_REQUIRES;
+		}
+		if (module.exports().length > 0) {
+			IPackageExport[] refs = module.exports();
+			mod.exports = new PackageExportInfo[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				PackageExportInfo exp = createPackageExport(refs[i]);
+				mod.exports[i] = exp;
+			}
+		} else {
+			mod.exports = NO_EXPORTS;
+		}
+		if (module.uses().length > 0) {
+			char[][] uses = module.uses();
+			mod.usedServices = new char[uses.length][];
+			for (int i = 0; i < uses.length; i++) {
+				mod.usedServices[i] = uses[i];
+			}
+		} else {
+			mod.usedServices = NO_USES;
+		}
+		if (module.provides().length > 0) {
+			IService[] provides = module.provides();
+			mod.services = new ServiceInfo[provides.length];
+			for (int i = 0; i < provides.length; i++) {
+				mod.services[i] = createService(provides[i]);
+			}
+		} else {
+			mod.services = NO_PROVIDES;
+		}
+		if (module.opens().length > 0) {
+			IPackageExport[] opens = module.opens();
+			mod.opens = new PackageExportInfo[opens.length];
+			for (int i = 0; i < opens.length; i++) {
+				PackageExportInfo op = createOpensInfo(opens[i]);
+				mod.opens[i] = op;
+			}
+		} else {
+			mod.opens = NO_OPENS;
+		}
+		return mod;
+	}
+	private static PackageExportInfo createPackageExport(IModule.IPackageExport ref) {
+		PackageExportInfo exp = new PackageExportInfo();
+		exp.pack = ref.name();
+		char[][] targets = ref.targets();
+		if (targets != null) {
+			exp.target = new char[targets.length][];
+			for(int j = 0; j < targets.length; j++) {
+				exp.target[j] = targets[j];
+			}
+		}
+		return exp;
+	}
+	private static PackageExportInfo createOpensInfo(IModule.IPackageExport opens) {
+		PackageExportInfo open = new PackageExportInfo();
+		open.pack = opens.name();
+		char[][] targets = opens.targets();
+		if (targets != null) {
+			open.target = new char[targets.length][];
+			for(int j = 0; j < targets.length; j++) {
+				open.target[j] = targets[j];
+			}
+		}
+		return open;
+	}
+
+	private static ServiceInfo createService(IModule.IService provides) {
+		ServiceInfo info = new ServiceInfo();
+		info.serviceName = provides.name();
+		char[][] implementations = provides.with();
+		info.implNames = new char[implementations.length][];
+		for(int i = 0; i < implementations.length; i++) {
+			info.implNames[i] = implementations[i];
+		}
+		return info;
+	}
+
+	public static ModuleDescriptionInfo createModule(ModuleDeclaration module) {
+		ModuleDescriptionInfo mod = new ModuleDescriptionInfo();
+		mod.name = module.moduleName;
+		if (module.requiresCount > 0) {
+			RequiresStatement[] refs = module.requires;
+			mod.requires = new ModuleReferenceInfo[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				mod.requires[i] = new ModuleReferenceInfo();
+				mod.requires[i].name = CharOperation.concatWith(refs[i].module.tokens, '.'); // Check why ModuleReference#tokens must be a char[][] and not a char[] or String;
+				mod.requires[i].modifiers = refs[i].modifiers;
+			}
+		} else {
+			mod.requires = NO_REQUIRES;
+		}
+		if (module.exportsCount > 0) {
+			ExportsStatement[] refs = module.exports;
+			mod.exports = new PackageExportInfo[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				PackageExportInfo exp = createPackageExport(refs[i]);
+				mod.exports[i] = exp;
+			}
+		} else {
+			mod.exports = NO_EXPORTS;
+		}
+		if (module.usesCount > 0) {
+			UsesStatement[] uses = module.uses;
+			mod.usedServices = new char[uses.length][];
+			for (int i = 0; i < uses.length; i++) {
+				mod.usedServices[i] = CharOperation.concatWith(uses[i].serviceInterface.getTypeName(), '.');
+			}
+		} else {
+			mod.usedServices = NO_USES;
+		}
+		if (module.servicesCount > 0) {
+			ProvidesStatement[] provides = module.services;
+			mod.services = new ServiceInfo[provides.length];
+			for (int i = 0; i < provides.length; i++) {
+				mod.services[i] = createService(provides[i]);
+			}
+		} else {
+			mod.services = NO_PROVIDES;
+		}
+		if (module.opensCount > 0) {
+			OpensStatement[] opens = module.opens;
+			mod.opens = new PackageExportInfo[opens.length];
+			for (int i = 0; i < opens.length; i++) {
+				PackageExportInfo op = createOpensInfo(opens[i]);
+				mod.opens[i] = op;
+			}
+		} else {
+			mod.opens = NO_OPENS;
+		}
+		return mod;
+	}
+
+	private static PackageExportInfo createPackageExport(ExportsStatement ref) {
+		PackageExportInfo exp = new PackageExportInfo();
+		exp.pack = ref.pkgName;
+		ModuleReference[] imp = ref.targets;
+		if (imp != null) {
+			exp.target = new char[imp.length][];
+			for(int j = 0; j < imp.length; j++) {
+				exp.target[j] = imp[j].moduleName;
+			}
+		}
+		return exp;
+	}
+	private static PackageExportInfo createOpensInfo(OpensStatement opens) {
+		PackageExportInfo open = new PackageExportInfo();
+		open.pack = opens.pkgName;
+		ModuleReference[] imp = opens.targets;
+		if (imp != null) {
+			open.target = new char[imp.length][];
+			for(int j = 0; j < imp.length; j++) {
+				open.target[j] = imp[j].moduleName;
+			}
+		}
+		return open;
+	}
+
+	private static ServiceInfo createService(ProvidesStatement provides) {
+		ServiceInfo info = new ServiceInfo();
+		info.serviceName = CharOperation.concatWith(provides.serviceInterface.getTypeName(), '.');
+		TypeReference[] implementations = provides.implementations;
+		info.implNames = new char[implementations.length][];
+		for(int i = 0; i < implementations.length; i++) {
+			info.implNames[i] = CharOperation.concatWith(implementations[i].getTypeName(), '.');
+		}
+		return info;
+	}
+
+	protected void setHandle(IModuleDescription handle) {
+		this.handle = handle;
+	}
+
+	public IJavaElement[] getChildren() {
+		return this.children;
+	}
+
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+
+	@Override
+	public IModule.IModuleReference[] requires() {
+		return this.requires;
+	}
+	@Override
+	public IPackageExport[] exports() {
+		return this.exports;
+	}
+
+	@Override
+	public char[][] uses() {
+		return this.usedServices;
+	}
+
+	@Override
+	public IService[] provides() {
+		return this.services;
+	}
+
+	@Override
+	public IPackageExport[] opens() {
+		return this.opens;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(getClass().getName());
+		toStringContent(buffer);
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer) {
+		buffer.append("\nmodule "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append('\n');
+		if (this.requires != null && this.requires.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.requires.length; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (this.requires[i].isTransitive()) {
+					buffer.append("transitive "); //$NON-NLS-1$
+				}
+				if (this.requires[i].isStatic()) {
+					buffer.append("static "); //$NON-NLS-1$
+				}
+				buffer.append(this.requires[i].name);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.exports != null && this.exports.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.exports.length; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(this.exports[i].toString()).append('\n');
+			}
+		}
+		if (this.usedServices != null && this.usedServices.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.usedServices.length; i++) {
+				buffer.append("\tuses "); //$NON-NLS-1$
+				buffer.append(this.usedServices[i].toString()).append('\n');
+			}
+		}
+		if (this.services != null && this.services.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.services.length; i++) {
+				buffer.append("\tprovides "); //$NON-NLS-1$
+				buffer.append(this.services[i].toString()).append('\n');
+			}
+		}
+		if (this.opens != null && this.opens.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.opens.length; i++) {
+				buffer.append("\topens "); //$NON-NLS-1$
+				buffer.append(this.opens[i].toString()).append('\n');
+			}
+		}
+		buffer.append('\n').append('}').toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleInfo.java
new file mode 100644
index 0000000..579d2f3
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleInfo.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
+import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.ModuleReferenceImpl;
+import org.eclipse.jdt.internal.compiler.env.PackageExportImpl;
+
+public class ModuleInfo extends SourceTypeElementInfo implements IModule {
+
+	protected static final IModuleReference[] NO_REQUIRES = new IModuleReference[0];
+	protected static final IPackageExport[] NO_EXPORTS = new IPackageExport[0];
+	protected static final IService[] NO_SERVICES = new IService[0];
+	protected static final char[][] NO_USES = new char[0][0];
+
+	static class Service implements IModule.IService {
+		char[] provides;
+		char[][] with;
+		@Override
+		public char[] name() {
+			return this.provides;
+		}
+
+		@Override
+		public char[][] with() {
+			return this.with;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append("provides "); //$NON-NLS-1$
+			buffer.append(this.provides);
+			buffer.append(" with "); //$NON-NLS-1$
+			buffer.append(this.with);
+			buffer.append(';');
+			return buffer.toString();
+		}
+	}
+	char[] name;
+	ModuleReferenceImpl[] requires;
+	PackageExportImpl[] exports;
+	char[][] uses;
+	Service[] provides;
+	PackageExportImpl[] opens;
+
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+	public static ModuleInfo createModule(ModuleDeclaration module) {
+		ModuleInfo mod = new ModuleInfo();
+		mod.name = module.moduleName;
+		if (module.requiresCount > 0) {
+			RequiresStatement[] refs = module.requires;
+			mod.requires = new ModuleReferenceImpl[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				mod.requires[i] = new ModuleReferenceImpl();
+				mod.requires[i].name = CharOperation.concatWith(refs[i].module.tokens, '.');
+				mod.requires[i].modifiers = refs[i].modifiers;
+			}
+		} else {
+			mod.requires = new ModuleReferenceImpl[0];
+		}
+		if (module.exportsCount > 0) {
+			ExportsStatement[] refs = module.exports;
+			mod.exports = new PackageExportImpl[refs.length];
+			for (int i = 0; i < refs.length; i++) {
+				PackageExportImpl exp = createPackageExport(refs, i);
+				mod.exports[i] = exp;
+			}
+		} else {
+			mod.exports = new PackageExportImpl[0];
+		}
+		if (module.usesCount > 0) {
+			UsesStatement[] uses = module.uses;
+			mod.uses = new char[uses.length][];
+			for(int i = 0; i < uses.length; i++) {
+				mod.uses[i] = CharOperation.concatWith(uses[i].serviceInterface.getTypeName(), '.');
+			}
+		}
+		if (module.servicesCount > 0) {
+			ProvidesStatement[] services = module.services;
+			mod.provides = new Service[module.servicesCount];
+			for (int i = 0; i < module.servicesCount; i++) {
+				mod.provides[i] = createService(services[i].serviceInterface, services[i].implementations);
+			}
+		}
+		return mod;
+	}
+
+	private static PackageExportImpl createPackageExport(ExportsStatement[] refs, int i) {
+		ExportsStatement ref = refs[i];
+		PackageExportImpl exp = new PackageExportImpl();
+		exp.pack = ref.pkgName;
+		ModuleReference[] imp = ref.targets;
+		if (imp != null) {
+			exp.exportedTo = new char[imp.length][];
+			for(int j = 0; j < imp.length; j++) {
+				exp.exportedTo[j] = imp[j].moduleName;
+			}
+		}
+		return exp;
+	}
+	private static Service createService(TypeReference service, TypeReference[] with) {
+		Service ser = new Service();
+		ser.provides = CharOperation.concatWith(service.getTypeName(), '.');
+		ser.with = new char[with.length][];
+		for (int i = 0; i < with.length; i++) {
+			ser.with[i] = CharOperation.concatWith(with[i].getTypeName(), '.');
+		}
+		return ser;
+	}
+
+	@Override
+	public IModule.IModuleReference[] requires() {
+		return this.requires;
+	}
+	@Override
+	public IPackageExport[] exports() {
+		return this.exports;
+	}
+	@Override
+	public char[][] uses() {
+		return this.uses;
+	}
+	@Override
+	public IService[] provides() {
+		return this.provides;
+	}
+	public IPackageExport[] opens() {
+		return this.opens;
+	}
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(getClass().getName());
+		toStringContent(buffer);
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer) {
+		buffer.append("\nmodule "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append('\n');
+		if (this.requires != null && this.requires.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.requires.length; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (this.requires[i].isTransitive()) {
+					buffer.append("public "); //$NON-NLS-1$
+				}
+				buffer.append(this.requires[i].name);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.exports != null && this.exports.length > 0) {
+			buffer.append('\n');
+			for(int i = 0; i < this.exports.length; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(this.exports[i].toString()).append('\n');
+			}
+		}
+		if (this.uses != null) {
+			buffer.append('\n');
+			for (char[] cs : this.uses) {
+				buffer.append(cs);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.provides != null) {
+			buffer.append('\n');
+			for(Service ser : this.provides) {
+				buffer.append('\t').append(ser.toString()).append('\n');
+			}
+		}
+		buffer.append('\n').append('}').toString();
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java
new file mode 100644
index 0000000..ca2293b
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainer.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+
+public class ModulePathContainer implements IClasspathContainer{
+
+	private IJavaProject project;
+
+	public ModulePathContainer(IJavaProject project) {
+		this.project = project;
+	}
+	@Override
+	public IClasspathEntry[] getClasspathEntries() {
+		//
+		List<IClasspathEntry> entries = new ArrayList<>();
+		ModuleSourcePathManager manager = JavaModelManager.getModulePathManager();
+		try {
+			AbstractModule module = (AbstractModule) ((JavaProject)this.project).getModuleDescription();
+			if (module == null)
+				return new IClasspathEntry[0];
+			for (org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference ref : module.getRequiredModules()) {
+				IModulePathEntry entry = manager.getModuleRoot(new String(ref.name()));
+				JavaProject refRoot = null;
+				if (entry instanceof ProjectEntry) {
+					refRoot = ((ProjectEntry) entry).project;
+				}
+				if (refRoot == null)
+					continue;
+				IPath path = refRoot.getPath();
+				entries.add(JavaCore.newProjectEntry(path, ref.isTransitive()));
+			}
+		} catch (JavaModelException e) {
+			// ignore
+		}
+		return entries.toArray(new IClasspathEntry[entries.size()]);
+	}
+
+	@Override
+	public String getDescription() {
+		// 
+		return "Module source path"; //$NON-NLS-1$
+	}
+
+	@Override
+	public int getKind() {
+		// 
+		return K_APPLICATION;
+	}
+
+	@Override
+	public IPath getPath() {
+		// 
+		return new Path(JavaCore.MODULE_PATH_CONTAINER_ID);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java
new file mode 100644
index 0000000..f28aebd
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModulePathContainerInitializer.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.ClasspathContainerInitializer;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class ModulePathContainerInitializer extends ClasspathContainerInitializer {
+
+	@Override
+	public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
+		//
+		if (isModulePathContainer(containerPath)) {
+			if (project instanceof JavaProject) {
+				// TODO: should project compliance level be checked here?
+				ModulePathContainer container = new ModulePathContainer(project);
+				JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { project },
+						new IClasspathContainer[] { container }, null);
+			}
+		} else if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) {
+			verbose_not_a_module_project(project, containerPath);
+		}
+	}
+	private boolean isModulePathContainer(IPath path) {
+		return path != null && JavaCore.MODULE_PATH_CONTAINER_ID.equals(path.segment(0));
+	}
+	private void verbose_not_a_module_project(IJavaProject project, IPath containerPath) {
+		Util.verbose(
+			"Module path INIT - FAILED (not a module project)\n" + //$NON-NLS-1$
+			"	project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+			"	container path: " + containerPath); //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java
new file mode 100644
index 0000000..ff75aa8
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleSourcePathManager.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+
+public class ModuleSourcePathManager {
+
+	private Map<String, IModulePathEntry> knownModules = new HashMap<String, IModulePathEntry>(11);
+
+	private IModulePathEntry getModuleRoot0(String name) {
+		return this.knownModules.get(name);
+	}
+	public IModulePathEntry getModuleRoot(String name) {
+		IModulePathEntry root = getModuleRoot0(name);
+		if (root == null) {
+			try {
+				seekModule(name.toCharArray(),false, new JavaElementRequestor());
+			} catch (JavaModelException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		root = this.knownModules.get(name);
+		return root;
+	}
+	public void addEntry(IModuleDescription module, JavaProject project) throws JavaModelException {
+		String moduleName = new String(module.getElementName().toCharArray());
+		IModulePathEntry entry = getModuleRoot0(moduleName);
+		if (entry != null) {
+			// TODO : Should we signal error via JavaModelException
+			return;
+		}
+		this.knownModules.put(moduleName, new ProjectEntry(project));
+	}
+	
+	interface IPrefixMatcherCharArray {
+		boolean matches(char[] prefix, char[] name);
+	}
+	public void seekModule(char[] name, boolean prefixMatch, IJavaElementRequestor requestor) throws JavaModelException {
+		if (name == null)
+			return;
+		IPrefixMatcherCharArray prefixMatcher = prefixMatch ? CharOperation.equals(name, CharOperation.ALL_PREFIX) ?
+				(x, y) -> true : CharOperation::prefixEquals : CharOperation :: equals;
+		IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
+		for (int i = 0; i < projects.length; i++) {
+			IJavaProject project = projects[i];
+			if (!project.getProject().isAccessible())
+				continue;
+			if (project instanceof JavaProject) {
+				IModuleDescription module = ((JavaProject) project).getModuleDescription();
+				if (module != null) {
+					if (prefixMatcher.matches(name, module.getElementName().toCharArray())) {
+						//addEntry(module, (JavaProject) project);
+						requestor.acceptModule(module);
+					}
+				}
+			}
+		}
+	}
+	public IModule getModule(char[] name) {
+		IModulePathEntry root = getModuleRoot0(CharOperation.charToString(name));
+		if (root != null)
+			try {
+				return root.getModule();
+			} catch (Exception e1) {
+				//
+				return null;
+			}
+		JavaElementRequestor requestor = new JavaElementRequestor();
+		try {
+			seekModule(name, false, requestor);
+		} catch (JavaModelException e) {
+			// 
+		}
+		IModuleDescription[] modules = requestor.getModules();
+		if (modules.length > 0) {
+			IModuleDescription module = modules[0];
+			try {
+				return (ModuleDescriptionInfo) ((JavaElement) module).getElementInfo();
+			} catch (JavaModelException e) {
+				e.printStackTrace();
+			}
+		}
+		return null; 
+	}
+//	public IModuleDeclaration[] getModules() {
+//		if (this.knownModules.size() == 0) {
+//			return new IModuleDeclaration[0];
+//		}
+//		List<IModuleDeclaration> modules = new ArrayList<IModuleDeclaration>();
+//		for (IModulePathEntry val : this.knownModules.values()) {
+//			try {
+//				modules.add(val.getModule());
+//			} catch (Exception e) {
+//				// TODO Auto-generated catch block
+//				e.printStackTrace();
+//			}
+//		}
+//		return modules.toArray(new IModuleDeclaration[modules.size()]);
+//	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index 58ea8fe..b1d3894 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -1,9 +1,13 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
@@ -13,17 +17,26 @@
 
 import java.io.File;
 import java.util.*;
-
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModel;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -32,6 +45,11 @@
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
@@ -58,14 +76,258 @@
  */
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class NameLookup implements SuffixConstants {
+	private final class AutoModule implements IModuleDescription {
+		String modName = null;
+		public AutoModule(String name) {
+			this.modName = name;
+		}
+		
+		@Override
+		public boolean hasChildren() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public IJavaElement[] getChildren() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public void rename(String name, boolean replace, IProgressMonitor monitor) throws JavaModelException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void move(IJavaElement container, IJavaElement sibling, String rename, boolean replace,
+				IProgressMonitor monitor) throws JavaModelException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean replace,
+				IProgressMonitor monitor) throws JavaModelException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public ISourceRange getSourceRange() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String getSource() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public ISourceRange getNameRange() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public <T> T getAdapter(Class<T> adapter) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public boolean isStructureKnown() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public boolean isReadOnly() {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public IResource getUnderlyingResource() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public ISchedulingRule getSchedulingRule() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IResource getResource() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IJavaElement getPrimaryElement() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IPath getPath() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IJavaElement getParent() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IOpenable getOpenable() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IJavaProject getJavaProject() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IJavaModel getJavaModel() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String getHandleIdentifier() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public int getElementType() {
+			return IJavaElement.JAVA_MODULE;
+		}
+
+		@Override
+		public String getElementName() {
+			return this.modName;
+		}
+
+		@Override
+		public IResource getCorrespondingResource() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IJavaElement getAncestor(int ancestorType) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public boolean exists() {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public boolean isBinary() {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public ITypeRoot getTypeRoot() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IType getType(String name, int occurrenceCount) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public int getOccurrenceCount() {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public ISourceRange getJavadocRange() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public int getFlags() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public IType getDeclaringType() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public ICompilationUnit getCompilationUnit() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public IClassFile getClassFile() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String[] getCategories() throws JavaModelException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+	}
+
 	public static class Answer {
 		public IType type;
+		public IModuleDescription module;
 		AccessRestriction restriction;
 		IClasspathEntry entry;
 		Answer(IType type, AccessRestriction restriction, IClasspathEntry entry) {
+			this(type, restriction, entry, null);
+		}
+		Answer(IType type, AccessRestriction restriction, IClasspathEntry entry, IModuleDescription module) {
 			this.type = type;
 			this.restriction = restriction;
 			this.entry = entry;
+			this.module = module;
+		}
+		Answer(IModuleDescription module) {
+			this.module = module;
+			this.restriction = null;
 		}
 		public boolean ignoreIfBetter() {
 			return this.restriction != null && this.restriction.ignoreIfBetter();
@@ -81,6 +343,61 @@
 			return otherAnswer.restriction != null
 				&& this.restriction.getProblemId() < otherAnswer.restriction.getProblemId();
 		}
+		public String toString() {
+			StringBuilder builder = new StringBuilder(this.type.toString());
+			builder.append("from ") //$NON-NLS-1$
+			.append(this.module);
+			return builder.toString();
+		}
+	}
+
+	private class Selector implements IJavaElementRequestor {
+		public List<IPackageFragment> pkgFragments;
+
+		public Selector(String moduleName) {
+			this.pkgFragments = new ArrayList<>();
+		}
+
+		@Override
+		public void acceptField(IField field) {
+			// do nothing
+		}
+
+		@Override
+		public void acceptInitializer(IInitializer initializer) {
+			// do nothing
+		}
+
+		@Override
+		public void acceptMemberType(IType type) {
+			// do nothing
+		}
+
+		@Override
+		public void acceptMethod(IMethod method) {
+			// do nothing
+		}
+
+		@Override
+		public void acceptPackageFragment(IPackageFragment packageFragment) {
+			this.pkgFragments.add(packageFragment);
+		}
+
+		@Override
+		public void acceptType(IType type) {
+			// do nothing
+		}
+
+		@Override
+		public void acceptModule(IModuleDescription module) {
+			// do nothing
+		}
+
+		@Override
+		public boolean isCanceled() {
+			// TODO Auto-generated method stub
+			return false;
+		}
 	}
 
 	// TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type)
@@ -616,6 +933,41 @@
 	}
 
 	/**
+	 * Find type in the given modules considering secondary types but without waiting for indexes.
+	 * It means that secondary types may be not found under certain circumstances...
+	 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
+	 */
+	public Answer findType(String typeName, String packageName, boolean partialMatch, int acceptFlags, boolean checkRestrictions, IModuleContext context) {
+		Answer suggestedAnswer = null;
+		if (context != IModuleContext.UNNAMED_MODULE_CONTEXT) {
+//			for (IModuleDeclaration module : modules) {
+				suggestedAnswer = findType(typeName, packageName, partialMatch, acceptFlags,
+						true/* consider secondary types */, false/* do NOT wait for indexes */, checkRestrictions,
+						null, context);
+//				if (answer != null) {
+//					if (!answer.ignoreIfBetter()) {
+//						if (answer.isBetter(suggestedAnswer))
+//							return answer;
+//					} else if (answer.isBetter(suggestedAnswer))
+//						// remember suggestion and keep looking
+//						suggestedAnswer = answer;
+//				}
+//			}
+			
+		} else {
+			suggestedAnswer = findType(typeName,
+					packageName,
+					partialMatch,
+					acceptFlags,
+					true/* consider secondary types */,
+					false/* do NOT wait for indexes */,
+					checkRestrictions,
+					null);
+		}
+		return suggestedAnswer;
+	}
+
+	/**
 	 * Find type considering secondary types but without waiting for indexes.
 	 * It means that secondary types may be not found under certain circumstances...
 	 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
@@ -630,7 +982,6 @@
 			checkRestrictions,
 			null);
 	}
-
 	/**
 	 * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
 	 */
@@ -643,6 +994,30 @@
 			boolean waitForIndexes,
 			boolean checkRestrictions,
 			IProgressMonitor monitor) {
+
+		return findType(typeName,
+				packageName,
+				partialMatch,
+				acceptFlags,
+				considerSecondaryTypes,
+				waitForIndexes,
+				checkRestrictions,
+				monitor,
+				IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+	/**
+	 * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
+	 */
+	public Answer findType(
+			String typeName,
+			String packageName,
+			boolean partialMatch,
+			int acceptFlags,
+			boolean considerSecondaryTypes,
+			boolean waitForIndexes,
+			boolean checkRestrictions,
+			IProgressMonitor monitor,
+			IModuleContext context) {
 		if (packageName == null || packageName.length() == 0) {
 			packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
 		} else if (typeName.length() > 0 && ScannerHelper.isLowerCase(typeName.charAt(0))) {
@@ -652,7 +1027,7 @@
 
 		// Look for concerned package fragments
 		JavaElementRequestor elementRequestor = new JavaElementRequestor();
-		seekPackageFragments(packageName, false, elementRequestor);
+		seekPackageFragments(packageName, false, elementRequestor, context);
 		IPackageFragment[] packages= elementRequestor.getPackageFragments();
 
 		// Try to find type in package fragments list
@@ -672,7 +1047,7 @@
 						accessRestriction = getViolatedRestriction(typeName, packageName, entry, accessRestriction);
 					}
 				}
-				Answer answer = new Answer(type, accessRestriction, entry);
+				Answer answer = new Answer (type, accessRestriction, entry, getModule(root));
 				if (!answer.ignoreIfBetter()) {
 					if (answer.isBetter(suggestedAnswer))
 						return answer;
@@ -731,6 +1106,34 @@
 		return type == null ? null : new Answer(type, null, null);
 	}
 
+	public static IModule getModuleDescriptionInfo(IModuleDescription moduleDesc) {
+		if (moduleDesc != null) {
+			try {
+				if (moduleDesc instanceof BinaryModule) {
+					return (ModuleDescriptionInfo)((BinaryModule) moduleDesc).getElementInfo();
+				} else if (moduleDesc instanceof SourceModule) {
+					return(ModuleDescriptionInfo)((SourceModule) moduleDesc).getElementInfo();
+				} else {
+					return new ModuleEnvironment.AutoModule(moduleDesc.getElementName().toCharArray());
+				}
+			} catch (JavaModelException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		return ModuleEnvironment.UNNAMED_MODULE;
+	}
+
+	private IModuleDescription getModule(PackageFragmentRoot root) {
+		return root.getModuleDescription();
+	}
+	public IModule getModuleDescriptionInfo(PackageFragmentRoot root) {
+		IModuleDescription desc = getModule(root);
+		if (desc != null) {
+			return getModuleDescriptionInfo(desc);
+		}
+		return null;
+	}
 	private AccessRestriction getViolatedRestriction(String typeName, String packageName, ClasspathEntry entry, AccessRestriction accessRestriction) {
 		AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
 		if (accessRuleSet != null) {
@@ -846,6 +1249,24 @@
 		}
 		return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor);
 	}
+	public Answer findModule(String moduleName) {
+		JavaElementRequestor requestor = new JavaElementRequestor();
+		char[] nameArray = moduleName.toCharArray();
+		seekModules(nameArray, requestor);
+		IModuleDescription[] modules = requestor.getModules();
+		if (modules.length == 0) {
+			try {
+				JavaModelManager.getModulePathManager().seekModule(nameArray, false, requestor);
+				modules = requestor.getModules();
+			} catch (JavaModelException e) {
+				// TODO Auto-generated catch block
+			}
+		}
+		if (modules.length > 0) { // TODO what to do??
+			return new Answer(modules[0]);
+		}
+		return null;
+	}
 
 	private IType getMemberType(IType type, String name, int dot) {
 		while (dot != -1) {
@@ -861,6 +1282,30 @@
 		return this.packageFragments.get(pkgName) != null;
 	}
 
+	public boolean isPackage(String[] pkgName, IModuleContext context) {
+		if (context == IModuleContext.UNNAMED_MODULE_CONTEXT)
+			return isPackage(pkgName);
+		
+		Object value = this.packageFragments.get(pkgName);
+		// TODO: need better representation of IModuleEnvironment and IModulePathEntry
+		// in the model to avoid this kind of comparison
+		return context.getEnvironment().anyMatch(e -> {
+			if (value instanceof PackageFragmentRoot) {
+				PackageFragmentRoot root = (PackageFragmentRoot)value;
+				return e.equals(e instanceof JavaProject ? root.getJavaProject() : root);
+			} else {
+				IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
+				if (roots != null) {
+					for (int i = 0, length = roots.length; i < length; i++) {
+						PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
+						if (e.equals(e instanceof JavaProject ? root.getJavaProject() : root))
+							return true;
+					}
+				}
+			}
+			return false;
+		});
+	}
 	/**
 	 * Returns true if the given element's name matches the
 	 * specified <code>searchName</code>, otherwise false.
@@ -907,13 +1352,110 @@
 	 * @param partialMatch partial name matches qualify when <code>true</code>;
 	 *	only exact name matches qualify when <code>false</code>
 	 */
+	public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor, IModuleContext context) {
+		if (context == IModuleContext.UNNAMED_MODULE_CONTEXT) {
+			seekPackageFragments(name, partialMatch, requestor);
+			return;
+		}
+		if (partialMatch) {
+			seekModuleAwarePartialPackageFragments(name, requestor, context);
+			return;
+		}
+		
+		String[] splittedName = Util.splitOn('.', name, 0, name.length());
+		int pkgIndex = this.packageFragments.getIndex(splittedName);
+		if (pkgIndex == -1)
+			return;
+		checkModulePackages(requestor, context, pkgIndex);
+		
+	}
+	/**
+	 * Notifies the given requestor of all package fragments with the
+	 * given name. Checks the requestor at regular intervals to see if the
+	 * requestor has canceled. The domain of
+	 * the search is bounded by the <code>IJavaProject</code>
+	 * this <code>NameLookup</code> was obtained from.
+	 *
+	 * @param partialMatch partial name matches qualify when <code>true</code>;
+	 *	only exact name matches qualify when <code>false</code>
+	 */
+	public void seekTypes(String pkgName, String name, boolean partialMatch, IJavaElementRequestor requestor, 
+			int acceptFlags, IModuleContext context, String moduleName) {
+		Selector selector = new Selector(moduleName);
+		seekPackageFragments(pkgName, true /*partialMatch*/, selector, context);	
+		if (selector.pkgFragments.size() == 0) return;
+		for (IPackageFragment pkg : selector.pkgFragments) {
+			seekTypes(name, pkg, partialMatch, acceptFlags, requestor);
+		}
+	}
+	
+	private void seekModuleAwarePartialPackageFragments(String name, IJavaElementRequestor requestor, IModuleContext context) {
+		boolean allPrefixMatch = CharOperation.equals(name.toCharArray(), CharOperation.ALL_PREFIX);
+		Arrays.stream(this.packageFragments.keyTable)
+		.filter(k -> k != null)
+		.filter(k -> allPrefixMatch || Util.concatWith((String[])k, '.').startsWith(name))
+		.forEach(k -> {
+			checkModulePackages(requestor, context, this.packageFragments.getIndex(k));
+		});
+	}
+
+	private void checkModulePackages(IJavaElementRequestor requestor, IModuleContext context, int pkgIndex) {
+		Object value = this.packageFragments.valueTable[pkgIndex];
+		// reuse existing String[]
+		String[] pkgName = (String[]) this.packageFragments.keyTable[pkgIndex];
+		context.getEnvironment().forEach(r -> {
+			if (value instanceof PackageFragmentRoot) {
+				Object toCompare = value;
+				// TODO: need better representation of IModuleEnvironment and IModulePathEntry
+				// in the model to avoid comparison based on instance
+				if (r instanceof JavaProject) {
+					toCompare  = ((PackageFragmentRoot)value).getJavaProject();
+				}
+				if (r.equals(toCompare)) {
+					PackageFragmentRoot root = (PackageFragmentRoot) value;
+					requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
+				}
+			} else {
+				IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
+				if (roots != null) {
+					for (int i = 0, length = roots.length; i < length; i++) {
+						if (requestor.isCanceled())
+							return;
+						PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
+						Object toCompare = root;
+						if (r instanceof JavaProject) {
+							toCompare  = root.getJavaProject();
+						}
+						if (r.equals(toCompare))
+							requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
+					}
+				}
+			}
+		});
+	}
+
+	@FunctionalInterface
+	interface IPrefixMatcherCharArray { // note the reversal in the order of params wrt to the string version.
+		boolean matches(char[] prefix, char[] name);
+	}
+	/**
+	 * Notifies the given requestor of all package fragments with the
+	 * given name. Checks the requestor at regular intervals to see if the
+	 * requestor has canceled. The domain of
+	 * the search is bounded by the <code>IJavaProject</code>
+	 * this <code>NameLookup</code> was obtained from.
+	 *
+	 * @param partialMatch partial name matches qualify when <code>true</code>;
+	 *	only exact name matches qualify when <code>false</code>
+	 */
 	public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
 /*		if (VERBOSE) {
 			Util.verbose(" SEEKING PACKAGE FRAGMENTS");  //$NON-NLS-1$
 			Util.verbose(" -> name: " + name);  //$NON-NLS-1$
 			Util.verbose(" -> partial match:" + partialMatch);  //$NON-NLS-1$
 		}
-*/		if (partialMatch) {
+*/
+		if (partialMatch) {
 			String[] splittedName = Util.splitOn('.', name, 0, name.length());
 			Object[][] keys = this.packageFragments.keyTable;
 			for (int i = 0, length = keys.length; i < length; i++) {
@@ -944,7 +1486,8 @@
 				// reuse existing String[]
 				String[] pkgName = (String[]) this.packageFragments.keyTable[pkgIndex];
 				if (value instanceof PackageFragmentRoot) {
-					requestor.acceptPackageFragment(((PackageFragmentRoot) value).getPackageFragment(pkgName));
+					PackageFragmentRoot root = (PackageFragmentRoot) value;
+					requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
 				} else {
 					IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
 					if (roots != null) {
@@ -964,6 +1507,65 @@
 		seekTypes(name, pkg, partialMatch, acceptFlags, requestor, true);
 	}
 
+	public void seekModuleReferences(String name, IJavaElementRequestor requestor, IJavaProject javaProject) {
+		seekModule(name.toCharArray(), true /* prefix */, requestor);
+	}
+	public void seekModule(char[] name, boolean prefixMatch, IJavaElementRequestor requestor) {
+
+		IPrefixMatcherCharArray prefixMatcher = prefixMatch ? CharOperation.equals(name, CharOperation.ALL_PREFIX) ?
+				(x, y) -> true : CharOperation::prefixEquals : CharOperation :: equals;
+
+		int count= this.packageFragmentRoots.length;
+		for (int i= 0; i < count; i++) {
+			if (requestor.isCanceled())
+				return;
+			IPackageFragmentRoot root= this.packageFragmentRoots[i];
+			IModuleDescription module = null;
+			if (root instanceof JrtPackageFragmentRoot) {
+				if (!prefixMatcher.matches(name, root.getElementName().toCharArray())) {
+					continue;
+				}
+			}
+			module = getModule((PackageFragmentRoot) root);
+			if (module != null) {
+				if (prefixMatcher.matches(name, module.getElementName().toCharArray()))
+				requestor.acceptModule(module);
+			} else {
+				String modName = root.getPath().removeFileExtension().lastSegment();
+				if (CharOperation.equals(modName.toCharArray(), name)) {
+					// ^^^ Only complete matches, at this point, as we don't propose automatic module names.
+					ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
+					if (entry != null && entry.isAutomaticModule()) {
+						requestor.acceptModule(new AutoModule(modName));
+					}
+				}
+			}
+		}
+	}
+	public IModuleEnvironment getModuleEnvironmentFor(char[] moduleName) throws JavaModelException {
+		String name = CharOperation.charToString(moduleName);
+		IModulePathEntry entry = JavaModelManager.getModulePathManager().getModuleRoot(name);
+		if (entry != null) {
+			IModule module = JavaModelManager.getModulePathManager().getModule(moduleName);
+			return entry.getLookupEnvironmentFor(module);
+		}
+		// revisit PackageFragmentRoot being a IModuleEnvironment
+		// It is not ideal to expect a java model element to cater to type lookup.
+		// Besides, the JrtPFR seemed to have only bogus implementation anyway.
+		int count= this.packageFragmentRoots.length;
+		for (int i= 0; i < count; i++) {
+			IPackageFragmentRoot root= this.packageFragmentRoots[i];
+			if (root instanceof JrtPackageFragmentRoot) {
+				if (CharOperation.equals(moduleName, root.getElementName().toCharArray())) {
+					return (IModuleEnvironment) root;
+				}
+			}
+		}
+		return null;
+	}
+	public void seekModules(char[] name, JavaElementRequestor requestor) {
+		seekModule(name, false, requestor);
+	}
 	/**
 	 * Notifies the given requestor of all types (classes and interfaces) in the
 	 * given package fragment with the given (unqualified) name.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
index 166182f..5973987 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -16,6 +20,7 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.ITypeParameter;
@@ -159,6 +164,14 @@
 		key.append(';');
 		return key.toString();
 	}
+	protected String getKey(IModuleDescription module, boolean forceOpen) throws JavaModelException {
+		StringBuffer key = new StringBuffer();
+		key.append('L');
+		String modName = module.getElementName();
+		key.append(modName);
+		key.append(';');
+		return key.toString();
+	}
 
 	protected String getFullyQualifiedParameterizedName(String fullyQualifiedName, String uniqueKey) throws JavaModelException {
 		String[] typeArguments = new BindingKey(uniqueKey).getTypeArguments();
@@ -293,6 +306,10 @@
 			public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selcetorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) {
 				// ignore
 			}
+			@Override
+			public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) {
+				// ignore
+			}
 
 		}
 		TypeResolveRequestor requestor = new TypeResolveRequestor();
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 5774763..6f87a4b 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
@@ -12,6 +12,9 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IModuleDescription;
+
+
 
 /** Element info for IOpenable elements. */
 public class OpenableElementInfo extends JavaElementInfo {
@@ -22,7 +25,7 @@
 	 * no children.
 	 */
 	protected volatile IJavaElement[] children = JavaElement.NO_ELEMENTS;
-	
+	protected IModuleDescription module;
 	/**
 	 * Is the structure of this element known
 	 * @see IJavaElement#isStructureKnown()
@@ -84,6 +87,12 @@
 		this.children = children;
 	}
 
+	public void setModule(IModuleDescription module) {
+		this.module = module;
+	}
+	public IModuleDescription getModule() {
+		return this.module;
+	}
 	/**
 	 * Sets whether the structure of this element known
 	 * @see IJavaElement#isStructureKnown()
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index beba74d..4944722 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -18,6 +22,7 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -196,6 +201,12 @@
 			char[][] inclusionPatterns = fullInclusionPatternChars();
 			char[][] exclusionPatterns = fullExclusionPatternChars();
 			computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), CharOperation.NO_STRINGS, vChildren, inclusionPatterns, exclusionPatterns);
+//			char[] suffix = getKind() == K_SOURCE ? SuffixConstants.SUFFIX_java : SuffixConstants.SUFFIX_class;
+//			char[] moduleInfoName = CharOperation.concat(TypeConstants.MODULE_INFO_NAME, suffix);
+//			IResource module = rootFolder.findMember(String.valueOf(moduleInfoName), true);
+//			if (module != null && module.exists()) {
+//				vChildren.add(new ClassFile(getPackageFragment(CharOperation.NO_STRINGS), String.valueOf(TypeConstants.MODULE_INFO_NAME)));
+//			}
 			IJavaElement[] children = new IJavaElement[vChildren.size()];
 			vChildren.toArray(children);
 			info.setChildren(children);
@@ -209,7 +220,7 @@
 }
 
 /**
- * Starting at this folder, create package fragments and add the fragments that are not exclused
+ * Starting at this folder, create package fragments and add the fragments that are not excluded
  * to the collection of children.
  *
  * @exception JavaModelException  The resource associated with this package fragment does not exist
@@ -478,6 +489,10 @@
 	((JavaElement)getParent()).getHandleMemento(buff);
 	buff.append(getHandleMementoDelimiter());
 	escapeMementoName(buff, path.toString());
+	if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(path.toOSString())) {
+		buff.append(getHandleMementoDelimiter());
+		escapeMementoName(buff, getElementName());
+	}
 }
 /**
  * @see IPackageFragmentRoot
@@ -517,6 +532,9 @@
 public PackageFragment getPackageFragment(String[] pkgName) {
 	return new PackageFragment(this, pkgName);
 }
+public PackageFragment getPackageFragment(String[] pkgName, String mod) {
+	return new PackageFragment(this, pkgName); // Overridden in JImageModuleFragmentBridge
+}
 /**
  * Returns the package name for the given folder
  * (which is a decendent of this root).
@@ -823,5 +841,47 @@
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, sourcePath));
 	}
 }
-
+/**
+ * Returns the relative path within an archive for the given class file name. In certain
+ * kind of archives, such as a JMOD file, class files are stored in a nested folder, as opposed
+ * to directly under the root. It is the responsibility of such package fragment roots to
+ * provide the custom behavior.
+ *
+ * @param classname
+ * @return the relative path for the class file within the archive
+ */
+public String getClassFilePath(String classname) {
+	return classname;
+}
+public IModuleDescription getModuleDescription() {
+	try {
+		IJavaElement[] pkgs = getChildren();
+		for (int j = 0, length = pkgs.length; j < length; j++) {
+			// only look in the default package
+			if (pkgs[j].getElementName().length() == 0) {
+				OpenableElementInfo info = null;
+				if (getKind() == IPackageFragmentRoot.K_SOURCE) {
+					ICompilationUnit unit = ((PackageFragment) pkgs[j])
+							.getCompilationUnit(TypeConstants.MODULE_INFO_FILE_NAME_STRING);
+					if (unit instanceof CompilationUnit && unit.exists()) {
+						info = (CompilationUnitElementInfo) ((CompilationUnit) unit)
+								.getElementInfo();
+						if (info != null)
+							return info.getModule();
+					}
+				} else {
+					IClassFile classFile = ((IPackageFragment)pkgs[j]).getClassFile(TypeConstants.MODULE_INFO_CLASS_NAME_STRING);
+					if (classFile instanceof ClassFile && classFile.exists()) {
+						return classFile.getModule();
+					}
+				}
+				break;
+			}
+		}
+	} catch (JavaModelException e) {
+		e.printStackTrace();
+		//
+	}
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
index b960b7e..9ad9fc6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
@@ -39,6 +39,7 @@
 
 	private boolean ignoreOptionalProblems;
 	private boolean initialized;
+
 /**
  * Create and initialize a new instance of the receiver
  */
@@ -145,6 +146,7 @@
 	}
 	return resources;
 }
+
 /**
  * Returns the kind of this root.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java
new file mode 100644
index 0000000..48a54bc
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectEntry.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+
+/**
+ * Represents a project
+ *
+ */
+public class ProjectEntry implements IModulePathEntry {
+
+	JavaProject project;
+	
+	public ProjectEntry(JavaProject project) {
+		// 
+		this.project = project;
+	}
+	@Override
+	public IModule getModule() {
+		try {
+			IModuleDescription module = this.project.getModuleDescription();
+			if (module != null) {
+				return (ModuleDescriptionInfo) ((JavaElement) module) .getElementInfo();
+			}
+		} catch (JavaModelException e) {
+			// Proceed with null;
+		}
+		return null;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironment() {
+		// 
+		return this.project;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironmentFor(IModule module) {
+		//
+		if (getModule() == module)
+			return this.project;
+		return null;
+	}
+	@Override
+	public boolean isAutomaticModule() {
+		return false;
+	}
+}
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 c44cba3..f3a28c1 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - contribution for bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
@@ -21,9 +25,13 @@
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
 import org.eclipse.jdt.internal.core.search.IRestrictedAccessConstructorRequestor;
@@ -37,7 +45,7 @@
  *	uses the Java model as a search tool.
  */
 public class SearchableEnvironment
-	implements INameEnvironment, IJavaSearchConstants {
+	implements IModuleAwareNameEnvironment, IJavaSearchConstants {
 
 	public NameLookup nameLookup;
 	protected ICompilationUnit unitToSkip;
@@ -91,7 +99,7 @@
 	 * Returns the given type in the the given package if it exists,
 	 * otherwise <code>null</code>.
 	 */
-	protected NameEnvironmentAnswer find(String typeName, String packageName) {
+	protected NameEnvironmentAnswer find(String typeName, String packageName, IModuleContext context) {
 		if (packageName == null)
 			packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
 		if (this.owner != null) {
@@ -107,12 +115,14 @@
 				packageName,
 				false/*exact match*/,
 				NameLookup.ACCEPT_ALL,
-				this.checkAccessRestrictions);
+				this.checkAccessRestrictions,
+				context);
 		if (answer != null) {
 			// construct name env answer
 			if (answer.type instanceof BinaryType) { // BinaryType
 				try {
-					return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction);
+					char[] moduleName = answer.module != null ? answer.module.getElementName().toCharArray() : null;
+					return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction, moduleName);
 				} catch (JavaModelException npe) {
 					// fall back to using owner
 				}
@@ -137,7 +147,8 @@
 						if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861)
 							sourceTypes[index++] = otherType;
 					}
-					return new NameEnvironmentAnswer(sourceTypes, answer.restriction, getExternalAnnotationPath(answer.entry));
+					char[] moduleName = answer.module != null ? answer.module.getElementName().toCharArray() : null;
+					return new NameEnvironmentAnswer(sourceTypes, answer.restriction, getExternalAnnotationPath(answer.entry), moduleName);
 				} catch (JavaModelException jme) {
 					if (jme.isDoesNotExist() && String.valueOf(TypeConstants.PACKAGE_INFO_NAME).equals(typeName)) {
 						// in case of package-info.java the type doesn't exist in the model,
@@ -161,6 +172,17 @@
 	}
 
 	/**
+	 * Find the modules that start with the given prefix.
+	 * A valid prefix is a qualified name separated by periods
+	 * (ex. java.util).
+	 * The packages found are passed to:
+	 *    ISearchRequestor.acceptModule(char[][] moduleName)
+	 */
+	public void findModules(char[] prefix, ISearchRequestor requestor, IJavaProject javaProject) {
+		this.nameLookup.seekModule(prefix, true, new SearchableEnvironmentRequestor(requestor));
+	}
+
+	/**
 	 * Find the packages that start with the given prefix.
 	 * A valid prefix is a qualified name separated by periods
 	 * (ex. java.util).
@@ -175,6 +197,19 @@
 	}
 
 	/**
+	 * Find the packages that start with the given prefix.
+	 * A valid prefix is a qualified name separated by periods
+	 * (ex. java.util).
+	 * The packages found are passed to:
+	 *    ISearchRequestor.acceptPackage(char[][] packageName)
+	 */
+	public void findPackages(char[] prefix, ISearchRequestor requestor, IModuleContext context) {
+		this.nameLookup.seekPackageFragments(
+			new String(prefix),
+			true,
+			new SearchableEnvironmentRequestor(requestor), context);
+	}
+	/**
 	 * Find the top-level types that are defined
 	 * in the current environment and whose simple name matches the given name.
 	 *
@@ -276,15 +311,15 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[][])
+	 * @see ModuleEnvironment#findType(char[][])
 	 */
-	public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
+	public NameEnvironmentAnswer findType(char[][] compoundTypeName, IModuleContext context) {
 		if (compoundTypeName == null) return null;
 
 		int length = compoundTypeName.length;
 		if (length <= 1) {
 			if (length == 0) return null;
-			return find(new String(compoundTypeName[0]), null);
+			return find(new String(compoundTypeName[0]), null, context);
 		}
 
 		int lengthM1 = length - 1;
@@ -293,18 +328,18 @@
 
 		return find(
 			new String(compoundTypeName[lengthM1]),
-			CharOperation.toString(packageName));
+			CharOperation.toString(packageName), context);
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[], char[][])
+	 * @see ModuleEnvironment#findType(char[], char[][])
 	 */
-	public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
+	public NameEnvironmentAnswer findType(char[] name, char[][] packageName, IModuleContext context) {
 		if (name == null) return null;
 
 		return find(
 			new String(name),
-			packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName));
+			packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName), context);
 	}
 
 	/**
@@ -695,9 +730,9 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#isPackage(char[][], char[])
+	 * @see ModuleEnvironment#isPackage(char[][], char[])
 	 */
-	public boolean isPackage(char[][] parentPackageName, char[] subPackageName) {
+	public boolean isPackage(char[][] parentPackageName, char[] subPackageName, IModuleContext moduleContext) {
 		String[] pkgName;
 		if (parentPackageName == null)
 			pkgName = new String[] {new String(subPackageName)};
@@ -710,7 +745,7 @@
 		}
 		return 
 			(this.owner != null && this.owner.isPackage(pkgName))
-			|| this.nameLookup.isPackage(pkgName);
+			|| this.nameLookup.isPackage(pkgName, moduleContext);
 	}
 
 	/**
@@ -735,4 +770,46 @@
 	public void cleanup() {
 		// nothing to do
 	}
+
+	@Override
+	public org.eclipse.jdt.internal.compiler.env.IModule getModule(char[] name) {
+		NameLookup.Answer answer = this.nameLookup.findModule(CharOperation.charToString(name));
+		IModule module = null;
+		if (answer != null) {
+			module = NameLookup.getModuleDescriptionInfo(answer.module);
+		}
+		return module;
+	}
+	public IModuleEnvironment getModuleEnvironmentFor(char[] moduleName) {
+		IModuleEnvironment env = null;
+		try {
+			env = this.nameLookup.getModuleEnvironmentFor(moduleName);
+		} catch (JavaModelException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return env;
+	}
+	@Override
+	public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
+		// 
+		return findType(compoundTypeName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+
+	@Override
+	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+		// 
+		return findType(typeName, packageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+
+	@Override
+	public boolean isPackage(char[][] parentPackageName, char[] packageName) {
+		// 
+		return isPackage(parentPackageName, packageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+	}
+
+	@Override
+	public IModule[] getAllAutomaticModules() {
+		return new IModule[0];
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
index 49bfd18..1a5ce90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
@@ -85,6 +86,9 @@
 public void acceptPackageFragment(IPackageFragment packageFragment) {
 	this.requestor.acceptPackage(packageFragment.getElementName().toCharArray());
 }
+public void acceptModule(IModuleDescription module) {
+	this.requestor.acceptModule(module.getElementName().toCharArray());
+}
 /**
  * @see IJavaElementRequestor
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index 305cfe6..0917ce1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -19,6 +23,7 @@
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
@@ -43,6 +48,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.core.NameLookup.Answer;
 import org.eclipse.jdt.internal.core.util.HandleFactory;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -168,6 +174,12 @@
 		acceptBinaryMethod(type, method, uniqueKey, isConstructor);
 	}
 }
+@Override
+public void acceptModule(char[] moduleName, char[] uniqueKey, int start, int end) {
+	IModuleDescription module = resolveModule(moduleName);
+	addElement(module);
+	// TODO: Implement use cases to construct modules from location/key
+}
 /**
  * Resolve the type.
  */
@@ -905,6 +917,13 @@
 	}
 	return this.elements;
 }
+protected IModuleDescription resolveModule(char[] moduleName) {
+	Answer answer = this.nameLookup.findModule(new String(moduleName));
+	if (answer != null) {
+		return answer.module;
+	}
+	return null;
+}
 /**
  * Resolve the type
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
index 4be663f..dde04c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IType;
 
@@ -52,6 +53,12 @@
 /**
  * @see IJavaElementRequestor
  */
+public void acceptModule(IModuleDescription module) {
+	// implements interface method	
+}
+/**
+ * @see IJavaElementRequestor
+ */
 public void acceptPackageFragment(IPackageFragment packageFragment) {
 	// implements interface method
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
index e950a9c..0b55153 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Kelly Campbell <kellyc@google.com> - Hangs in SourceMapper during java proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=281575
@@ -13,6 +17,8 @@
 package org.eclipse.jdt.internal.core;
 
 import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -60,6 +66,7 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter;
@@ -281,6 +288,7 @@
 			// use no encoding
 		}
 		if (rootPath != null) {
+			this.rootPath = rootPath;
 			this.rootPaths = new ArrayList();
 			this.rootPaths.add(rootPath);
 		}
@@ -453,6 +461,62 @@
 		return -1;
 	}
 
+	class JrtPackageNamesAdderVisitor implements JRTUtil.JrtFileVisitor<java.nio.file.Path> {
+
+		public final HashSet firstLevelPackageNames;
+		final IPackageFragmentRoot root;
+		public String sourceLevel = null;
+		public String complianceLevel = null;
+		public boolean containsADefaultPackage;
+		public boolean containsJavaSource;
+
+		JrtPackageNamesAdderVisitor(HashSet firstLevelPackageNames, String sourceLevel, String complianceLevel,
+				boolean containsADefaultPackage, boolean containsJavaSource, IPackageFragmentRoot root) {
+			this.firstLevelPackageNames = firstLevelPackageNames;
+			this.root = root;
+			this.sourceLevel = sourceLevel;
+			this.complianceLevel = complianceLevel;
+			this.containsADefaultPackage = containsADefaultPackage;
+			this.containsJavaSource = containsJavaSource;
+		}
+		
+		@Override
+		public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+		
+		@Override
+		public FileVisitResult visitFile(java.nio.file.Path file, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException {
+			String entryName = file.toString();
+			if (Util.isClassFileName(entryName)) {
+				int index = entryName.indexOf('/');
+				if (index != -1) {
+					String firstLevelPackageName = entryName.substring(0, index);
+					if (!this.firstLevelPackageNames.contains(firstLevelPackageName)) {
+						if (this.sourceLevel == null) {
+							IJavaProject project = this.root.getJavaProject();
+							this.sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+							this.complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+						}
+						IStatus status = JavaConventions.validatePackageName(firstLevelPackageName, this.sourceLevel, this.complianceLevel);
+						if (status.isOK() || status.getSeverity() == IStatus.WARNING) {
+							this.firstLevelPackageNames.add(firstLevelPackageName);
+						}
+					}
+				} else {
+					this.containsADefaultPackage = true;
+				}
+			} else if (!this.containsJavaSource && org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(entryName)) {
+				this.containsJavaSource = true;
+			}
+			return FileVisitResult.CONTINUE;
+		}
+
+		@Override
+		public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	}
 	private synchronized void computeAllRootPaths(IType type) {
 		if (this.areRootPathsComputed) {
 			return;
@@ -471,7 +535,22 @@
 
 		String sourceLevel = null;
 		String complianceLevel = null;
-		if (root.isArchive()) {
+		if (Util.isJrt(pkgFragmentRootPath.toOSString())) {
+			try {
+				JrtPackageNamesAdderVisitor jrtPackageNamesAdderVisitor = new JrtPackageNamesAdderVisitor(firstLevelPackageNames, 
+						sourceLevel, complianceLevel, containsADefaultPackage, containsJavaSource, root);
+				org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(root.getPath().toFile(), jrtPackageNamesAdderVisitor, JRTUtil.NOTIFY_FILES);
+				sourceLevel = jrtPackageNamesAdderVisitor.sourceLevel;
+				complianceLevel = jrtPackageNamesAdderVisitor.complianceLevel;
+				containsADefaultPackage = jrtPackageNamesAdderVisitor.containsADefaultPackage;
+				containsJavaSource = jrtPackageNamesAdderVisitor.containsJavaSource;
+			} catch (IOException e) {
+				// We are not reading any specific file, so, move on for now
+				if (VERBOSE) {
+					e.printStackTrace();
+				}
+			}
+		} else if (root.isArchive()) {
 			JavaModelManager manager = JavaModelManager.getJavaModelManager();
 			ZipFile zip = null;
 			try {
@@ -1007,6 +1086,9 @@
 
 			if (this.rootPath != null) {
 				source = getSourceForRootPath(this.rootPath, name);
+				if (source == null) {
+					source = getSourceForRootPath("", name); //$NON-NLS-1$
+				}
 			}
 	
 			if (source == null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java
new file mode 100644
index 0000000..f4d5b05
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceModule.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.JavaModelException;
+
+public class SourceModule extends AbstractModule {
+	public SourceModule(JavaElement parent, String name) {
+		super(parent, name);
+	}
+	@Override
+	public int getFlags() throws JavaModelException {
+		ModuleDescriptionInfo info = (ModuleDescriptionInfo) getElementInfo();
+		return info.getModifiers();
+	}
+	public String toString(String lineDelimiter) {
+		StringBuffer buffer = new StringBuffer();
+		try {
+			toStringContent(buffer, lineDelimiter);
+		} catch (JavaModelException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index ac2dc19..72a3443 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -209,7 +213,6 @@
 protected void acceptSecondaryType(ClassFile classFile) {
 	// noop
 }
-
 protected void addAllSourceFiles(final ArrayList sourceFiles) throws CoreException {
 	for (int i = 0, l = this.sourceLocations.length; i < l; i++) {
 		final ClasspathMultiDirectory sourceLocation = this.sourceLocations[i];
@@ -229,7 +232,8 @@
 								if (exclusionPatterns != null || inclusionPatterns != null)
 									if (Util.isExcluded(resource.getFullPath(), inclusionPatterns, exclusionPatterns, false))
 										return false;
-								sourceFiles.add(new SourceFile((IFile) resource, sourceLocation));
+								SourceFile unit = new SourceFile((IFile) resource, sourceLocation);
+								sourceFiles.add(unit);
 							}
 							return false;
 						case IResource.FOLDER :
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BasicModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BasicModule.java
new file mode 100644
index 0000000..17d7086
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BasicModule.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.ModuleReferenceImpl;
+
+public class BasicModule implements IModule {
+	static class PackageExport implements IModule.IPackageExport {
+		char[] pack;
+		char[][] exportedTo;
+		@Override
+		public char[] name() {
+			return this.pack;
+		}
+
+		@Override
+		public char[][] targets() {
+			return this.exportedTo;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(this.pack);
+			if (this.exportedTo != null) {
+				for (char[] cs : this.exportedTo) {
+					buffer.append(cs);
+				}
+			}
+			buffer.append(';');
+			return buffer.toString();
+		}
+	}
+	static class Service implements IModule.IService {
+		char[] provides;
+		char[][] with;
+		@Override
+		public char[] name() {
+			return this.provides;
+		}
+
+		@Override
+		public char[][] with() {
+			return this.with;
+		}
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append("provides"); //$NON-NLS-1$
+			buffer.append(this.provides);
+			buffer.append(" with "); //$NON-NLS-1$
+			for (int i = 0; i < this.with.length; i++) {
+				buffer.append(this.with[i]);
+				if (i < this.with.length - 1)
+					buffer.append(", "); //$NON-NLS-1$
+			}
+			buffer.append(';');
+			return buffer.toString();
+		}
+	}
+
+	char[] name;
+	IModule.IModuleReference[] requires;
+	IModule.IPackageExport[] exports;
+	char[][] uses;
+	Service[] provides;
+	IModule.IPackageExport[] opens;
+	ClasspathLocation root;
+	boolean isAutomodule;
+	public BasicModule(char[] name, ClasspathLocation root, boolean isAutomodule) {
+		this.name = name;
+		this.root = root;
+		this.exports = IModule.NO_EXPORTS;
+		this.requires = IModule.NO_MODULE_REFS;
+		this.isAutomodule = isAutomodule;
+	}
+	@Override
+	public char[] name() {
+		return this.name;
+	}
+	@Override
+	public IModule.IModuleReference[] requires() {
+		return this.requires;
+	}
+	@Override
+	public IModule.IPackageExport[] exports() {
+		return this.exports;
+	}
+	@Override
+	public char[][] uses() {
+		return this.uses;
+	}
+	@Override
+	public IService[] provides() {
+		return this.provides;
+	}
+	@Override
+	public IPackageExport[] opens() {
+		return this.opens;
+	}
+	@Override
+	public boolean isAutomatic() {
+		return this.root.isAutomaticModule();
+	}
+	public void addReads(char[] modName) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n));
+		};
+		if (shouldAdd.test(modName)) {
+			int len = this.requires.length;
+			this.requires = Arrays.copyOf(this.requires, len + 1);
+			ModuleReferenceImpl info = new ModuleReferenceImpl();
+			info.name = modName;
+			this.requires[len] = info;
+		}		
+	}
+	public void addExports(IModule.IPackageExport[] toAdd) {
+		Predicate<char[]> shouldAdd = m -> {
+			return Stream.of(this.exports).map(ref -> ((PackageExport) ref).pack).noneMatch(n -> CharOperation.equals(m, n));
+		};
+		Collection<IPackageExport> merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd)
+				.filter(e -> shouldAdd.test(((PackageExport )e).name()))
+				.map(e -> {
+					PackageExport exp = new PackageExport();
+					exp.pack = ((PackageExport )e).name();
+					exp.exportedTo = ((PackageExport )e).targets();
+					return exp;
+				}))
+			.collect(
+				ArrayList::new,
+				ArrayList::add,
+				ArrayList::addAll);
+		this.exports = merged.toArray(new PackageExport[merged.size()]);
+	}
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (!(o instanceof IModule))
+			return false;
+		IModule mod = (IModule) o;
+		if (!CharOperation.equals(this.name, mod.name()))
+			return false;
+		return Arrays.equals(this.requires, mod.requires());
+	}
+	@Override
+	public int hashCode() {
+		int result = 17;
+		int c = this.name.hashCode();
+		result = 31 * result + c;
+		c =  Arrays.hashCode(this.requires);
+		result = 31 * result + c;
+		return result;
+	}
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(getClass().getName());
+		toStringContent(buffer);
+		return buffer.toString();
+	}
+	protected void toStringContent(StringBuffer buffer) {
+		buffer.append("\nmodule "); //$NON-NLS-1$
+		buffer.append(this.name).append(' ');
+		buffer.append('{').append('\n');
+		if (this.requires != null) {
+			for(int i = 0; i < this.requires.length; i++) {
+				buffer.append("\trequires "); //$NON-NLS-1$
+				if (this.requires[i].isTransitive()) {
+					buffer.append(" public "); //$NON-NLS-1$
+				}
+				buffer.append(this.requires[i].name());
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.exports != null) {
+			buffer.append('\n');
+			for(int i = 0; i < this.exports.length; i++) {
+				buffer.append("\texports "); //$NON-NLS-1$
+				buffer.append(this.exports[i].toString());
+			}
+		}
+		if (this.uses != null) {
+			buffer.append('\n');
+			for (char[] cs : this.uses) {
+				buffer.append(cs);
+				buffer.append(';').append('\n');
+			}
+		}
+		if (this.provides != null) {
+			buffer.append('\n');
+			for(Service ser : this.provides) {
+				buffer.append(ser.toString());
+			}
+		}
+		buffer.append('\n').append('}').toString();
+	}
+}
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 fa1e11d..21107db 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -13,17 +17,27 @@
 import java.io.IOException;
 import java.util.zip.ZipFile;
 
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment.AutoModule;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.Util;
 
+
 public class ClasspathDirectory extends ClasspathLocation {
 
 IContainer binaryFolder; // includes .class files for a single directory
@@ -33,14 +47,24 @@
 AccessRuleSet accessRuleSet;
 ZipFile annotationZipFile;
 String externalAnnotationPath;
+INameEnvironment env;
 
-ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
+ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean isAutomodule) {
 	this.binaryFolder = binaryFolder;
 	this.isOutputFolder = isOutputFolder || binaryFolder.getProjectRelativePath().isEmpty(); // if binaryFolder == project, then treat it as an outputFolder
 	this.directoryCache = new SimpleLookupTable(5);
 	this.accessRuleSet = accessRuleSet;
+	this.env = env;
 	if (externalAnnotationPath != null)
 		this.externalAnnotationPath = externalAnnotationPath.toOSString();
+	if (isAutomodule) {
+		setAutomaticModule();
+	}
+}
+
+void setAutomaticModule() {
+	this.isAutoModule = true;
+	acceptModule(new AutoModule(this.binaryFolder.getName().toCharArray()));
 }
 
 public void cleanup() {
@@ -54,6 +78,33 @@
 	this.directoryCache = null;
 }
 
+ClasspathDirectory initializeModule() {
+	IResource[] members = null;
+	try {
+		members = this.binaryFolder.members();
+		if (members != null) {
+			for (int i = 0, l = members.length; i < l; i++) {
+				IResource m = members[i];
+				String name = m.getName();
+				// Note: Look only inside the default package.
+				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
+					if (name.equalsIgnoreCase(IModuleEnvironment.MODULE_INFO_CLASS)) {
+						try {
+							this.acceptModule( Util.newClassFileReader(m));
+							this.isAutoModule = false;
+						} catch (ClassFormatException | IOException e) {
+							// TODO BETA_JAVA9 Auto-generated catch block
+							e.printStackTrace();
+						}
+					}
+				}
+			}
+		}
+	} catch (CoreException e1) {
+		e1.printStackTrace();
+	}
+	return this;
+}
 String[] directoryList(String qualifiedPackageName) {
 	String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName);
 	if (dirList == this.missingPackageHolder) return null; // package exists in another classpath directory or jar
@@ -67,9 +118,11 @@
 			int index = 0;
 			for (int i = 0, l = members.length; i < l; i++) {
 				IResource m = members[i];
-				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(m.getName()))
+				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++] = m.getName();
+					dirList[index++] = name;
+				}
 			}
 			if (index < dirList.length)
 				System.arraycopy(dirList, 0, dirList = new String[index], 0, index);
@@ -82,7 +135,11 @@
 	this.directoryCache.put(qualifiedPackageName, this.missingPackageHolder);
 	return null;
 }
-
+void acceptModule(ClassFileReader classfile) {
+	if (classfile != null) {
+		acceptModule(classfile.getModuleDeclaration());
+	}
+}
 boolean doesFileExist(String fileName, String qualifiedPackageName, String qualifiedFullName) {
 	String[] dirList = directoryList(qualifiedPackageName);
 	if (dirList == null) return false; // most common case
@@ -101,10 +158,12 @@
 	if (this.accessRuleSet != dir.accessRuleSet)
 		if (this.accessRuleSet == null || !this.accessRuleSet.equals(dir.accessRuleSet))
 			return false;
+	if (this.module != dir.module)
+		if (this.module == null || !this.module.equals(dir.module))
+			return false;
 	return this.binaryFolder.equals(dir.binaryFolder);
 }
-
-public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
 	if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case
 
 	IBinaryType reader = null;
@@ -118,6 +177,10 @@
 		return null;
 	}
 	if (reader != null) {
+		char[] modName = this.module == null ? null : this.module.name();
+		if (reader instanceof ClassFileReader) {
+			((ClassFileReader) reader).moduleName = modName;
+		}
 		String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
 		if (this.externalAnnotationPath != null) {
 			try {
@@ -132,8 +195,8 @@
 			}
 		}
 		if (this.accessRuleSet == null)
-			return new NameEnvironmentAnswer(reader, null);
-		return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
+			return this.module == null ? new NameEnvironmentAnswer(reader, null) : new NameEnvironmentAnswer(reader, null, modName);
+		return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()), modName);
 	}
 	return null;
 }
@@ -173,5 +236,21 @@
 	return this.binaryFolder.getFullPath().toString();
 }
 
+@Override
+public ITypeLookup typeLookup() {
+	//
+	return this::findClass;
+}
+
+@Override
+public IPackageLookup packageLookup() {
+	return this::isPackage;
+}
+
+@Override
+public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	// 
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+}
 
 }
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
new file mode 100644
index 0000000..5de8cf9
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.io.BufferedInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ClasspathJMod extends ClasspathJar {
+
+	public static char[] CLASSES = "classes".toCharArray(); //$NON-NLS-1$
+	public static char[] CLASSES_FOLDER = "classes/".toCharArray(); //$NON-NLS-1$
+	private static int MODULE_DESCRIPTOR_NAME_LENGTH = MODULE_INFO_CLASS.length();
+
+	ClasspathJMod(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env) {
+		super(zipFilename, lastModified, accessRuleSet, externalAnnotationPath, env, true);
+	}
+
+
+	public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		// TOOD: BETA_JAVA9 - Should really check for packages with the module context
+		if (!isPackage(qualifiedPackageName)) return null; // most common case
+
+		try {
+			qualifiedBinaryFileName = new String(CharOperation.append(CLASSES_FOLDER, qualifiedBinaryFileName.toCharArray()));
+			IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
+			if (reader != null) {
+				if (reader instanceof ClassFileReader) {
+					ClassFileReader classReader = (ClassFileReader) reader;
+					if (classReader.moduleName == null) {
+						classReader.moduleName = this.module == null ? null : this.module.name();
+					}
+				}
+				String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+				if (this.externalAnnotationPath != null) {
+					try {
+						if (this.annotationZipFile == null) {
+							this.annotationZipFile = ExternalAnnotationDecorator
+									.getAnnotationZipFile(this.externalAnnotationPath, null);
+						}
+
+						reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath,
+								fileNameWithoutExtension, this.annotationZipFile);
+					} catch (IOException e) {
+						// don't let error on annotations fail class reading
+					}
+				}
+				if (this.accessRuleSet == null)
+					return new NameEnvironmentAnswer(reader, null);
+				return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
+			}
+		} catch (IOException e) { // treat as if class file is missing
+		} catch (ClassFormatException e) { // treat as if class file is missing
+		}
+		return null;
+	}
+	protected String readJarContent(final SimpleSet packageSet) {
+		String modInfo = null;
+		for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+			ZipEntry entry = e.nextElement();
+			char[] entryName = entry.getName().toCharArray();
+			int index = CharOperation.indexOf('/', entryName);
+			if (index != -1) {
+				char[] folder = CharOperation.subarray(entryName, 0, index);
+				if (CharOperation.equals(CLASSES, folder)) {
+					char[] fileName = CharOperation.subarray(entryName, index + 1, entryName.length);
+					if (modInfo == null && fileName.length == MODULE_DESCRIPTOR_NAME_LENGTH) {
+						if (CharOperation.equals(fileName, MODULE_INFO_CLASS.toCharArray())) {
+							InputStream stream = null;
+							InputStream inputStream;
+							try {
+								inputStream = this.zipFile.getInputStream(entry);
+								if (inputStream == null) throw new IOException("Invalid zip entry name : " + entry.getName()); //$NON-NLS-1$
+								stream = new BufferedInputStream(inputStream);
+								byte[] content = Util.getInputStreamAsByteArray(stream, (int) entry.getSize());
+								DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("c:\\temp\\module-info.class"))); //$NON-NLS-1$
+								dos.write(content);
+								dos.close();
+//								FileWriter writer = new FileWriter(new File("c:\\temp\\module-info.class")); //$NON-NLS-1$
+							} catch (IOException e1) {
+								// TODO Auto-generated catch block
+								e1.printStackTrace();
+							}
+							modInfo = new String(entryName);
+						}
+					}
+					addToPackageSet(packageSet, new String(fileName), false);
+				}
+			}
+		}
+		return modInfo;
+	}
+}
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 20fe32f..700928e 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Tal Lev-Ami - added package cache for zip files
@@ -28,15 +32,22 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment.AutoModule;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.Util;
 
 @SuppressWarnings("rawtypes")
-public class ClasspathJar extends ClasspathLocation {
+public class ClasspathJar extends ClasspathLocation implements IModulePathEntry {
 
 static class PackageCacheEntry {
 	long lastModified;
@@ -50,40 +61,71 @@
 	}
 }
 
-static SimpleLookupTable PackageCache = new SimpleLookupTable();
+protected static SimpleLookupTable PackageCache = new SimpleLookupTable();
+protected static SimpleLookupTable ModuleCache = new SimpleLookupTable();
+INameEnvironment env = null;
+
+protected static void addToPackageSet(SimpleSet packageSet, String fileName, boolean endsWithSep) {
+	int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/');
+	while (last > 0) {
+		// extract the package name
+		String packageName = fileName.substring(0, last);
+		if (packageSet.addIfNotIncluded(packageName) == null)
+			return; // already existed
+		last = packageName.lastIndexOf('/');
+	}
+}
 
 /**
  * Calculate and cache the package list available in the zipFile.
- * @param jar The ClasspathJar to use
  * @return A SimpleSet with the all the package names in the zipFile.
  */
-static SimpleSet findPackageSet(ClasspathJar jar) {
-	String zipFileName = jar.zipFilename;
-	long lastModified = jar.lastModified();
-	long fileSize = new File(zipFileName).length();
+protected SimpleSet findPackageSet() {
+	String zipFileName = this.zipFilename;
 	PackageCacheEntry cacheEntry = (PackageCacheEntry) PackageCache.get(zipFileName);
-	if (cacheEntry != null && cacheEntry.lastModified == lastModified && cacheEntry.fileSize == fileSize)
+	long timestamp = this.lastModified();
+	long fileSize = new File(zipFileName).length();
+	if (cacheEntry != null && cacheEntry.lastModified == timestamp && cacheEntry.fileSize == fileSize) {
+		this.module = (IModule) ModuleCache.get(zipFileName);
 		return cacheEntry.packageSet;
-
-	SimpleSet packageSet = new SimpleSet(41);
+	}
+	final SimpleSet packageSet = new SimpleSet(41);
 	packageSet.add(""); //$NON-NLS-1$
-	nextEntry : for (Enumeration e = jar.zipFile.entries(); e.hasMoreElements(); ) {
-		String fileName = ((ZipEntry) e.nextElement()).getName();
-
-		// add the package name & all of its parent packages
-		int last = fileName.lastIndexOf('/');
-		while (last > 0) {
-			// extract the package name
-			String packageName = fileName.substring(0, last);
-			if (packageSet.addIfNotIncluded(packageName) == null)
-				continue nextEntry; // already existed
-			last = packageName.lastIndexOf('/');
+	String modInfo = readJarContent(packageSet);
+	PackageCache.put(zipFileName, new PackageCacheEntry(timestamp, fileSize, packageSet));
+	if (modInfo != null) {
+		try {
+			this.acceptModule(ClassFileReader.read(this.zipFile, modInfo));
+		} catch (ClassFormatException | IOException e) {
+			// TODO BETA_JAVA9 Auto-generated catch block
+			e.printStackTrace();
 		}
 	}
-
-	PackageCache.put(zipFileName, new PackageCacheEntry(lastModified, fileSize, packageSet));
 	return packageSet;
 }
+protected String readJarContent(final SimpleSet packageSet) {
+	String modInfo = null;
+	for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
+		String fileName = ((ZipEntry) e.nextElement()).getName();
+		if (modInfo == null) {
+			int folderEnd = fileName.lastIndexOf('/');
+			folderEnd += 1;
+			String className = fileName.substring(folderEnd, fileName.length());
+			if (className.equalsIgnoreCase(MODULE_INFO_CLASS)) {
+				modInfo = fileName;
+			}
+		}
+		addToPackageSet(packageSet, fileName, false);
+	}
+	return modInfo;
+}
+void acceptModule(ClassFileReader classfile) {
+	if (classfile != null) {
+		IModule mod = classfile.getModuleDeclaration();
+		ModuleCache.put(this.zipFilename, mod);
+		acceptModule(mod);
+	}
+}
 
 
 String zipFilename; // keep for equals
@@ -92,11 +134,11 @@
 ZipFile annotationZipFile;
 long lastModified;
 boolean closeZipFileAtEnd;
-SimpleSet knownPackageNames;
+private SimpleSet knownPackageNames;
 AccessRuleSet accessRuleSet;
 String externalAnnotationPath;
 
-ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
+ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean isAutomodule) {
 	this.resource = resource;
 	try {
 		java.net.URI location = resource.getLocationURI();
@@ -114,28 +156,50 @@
 	this.accessRuleSet = accessRuleSet;
 	if (externalAnnotationPath != null)
 		this.externalAnnotationPath = externalAnnotationPath.toString();
+	if (isAutomodule)
+		setAutomaticModule();
 }
 
-ClasspathJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
+ClasspathJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean isAutomodule) {
 	this.zipFilename = zipFilename;
 	this.lastModified = lastModified;
 	this.zipFile = null;
 	this.knownPackageNames = null;
 	this.accessRuleSet = accessRuleSet;
+	this.env = env;
 	if (externalAnnotationPath != null)
 		this.externalAnnotationPath = externalAnnotationPath.toString();
+	if (isAutomodule)
+		setAutomaticModule();
 }
 
-public ClasspathJar(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
-	this.zipFilename = zipFile.getName();
+public ClasspathJar(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean isAutomodule) {
+	this(zipFile.getName(), accessRuleSet, externalAnnotationPath, env, isAutomodule);
 	this.zipFile = zipFile;
-	this.closeZipFileAtEnd = false;
-	this.knownPackageNames = null;
-	this.accessRuleSet = accessRuleSet;
-	if (externalAnnotationPath != null)
-		this.externalAnnotationPath = externalAnnotationPath.toString();
+	this.closeZipFileAtEnd = true;
 }
 
+public ClasspathJar(String fileName, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean isAutomodule) {
+	this(fileName, 0, accessRuleSet, externalAnnotationPath, env, isAutomodule);
+	if (externalAnnotationPath != null)
+		this.externalAnnotationPath = externalAnnotationPath.toString();
+	if (isAutomodule)
+		setAutomaticModule();
+}
+
+void setAutomaticModule() {
+	this.isAutoModule = true;
+	acceptModule(new AutoModule(getFileName(this.zipFilename).toCharArray()));
+}
+private static String getFileName(String name) {
+	int index = name.lastIndexOf('.');
+	if (index != -1)
+		name = name.substring(0, index);
+	index = name.lastIndexOf(File.separatorChar);
+	if (index == -1)
+		return name;
+	return name.substring(index + 1);
+}
 public void cleanup() {
 	if (this.closeZipFileAtEnd) {
 		if (this.zipFile != null) {
@@ -159,20 +223,29 @@
 public boolean equals(Object o) {
 	if (this == o) return true;
 	if (!(o instanceof ClasspathJar)) return false;
-
 	ClasspathJar jar = (ClasspathJar) o;
 	if (this.accessRuleSet != jar.accessRuleSet)
 		if (this.accessRuleSet == null || !this.accessRuleSet.equals(jar.accessRuleSet))
 			return false;
-	return this.zipFilename.equals(jar.zipFilename) && lastModified() == jar.lastModified();
+	return this.zipFilename.equals(jar.zipFilename) 
+			&& lastModified() == jar.lastModified()
+			&& this.isAutoModule == jar.isAutoModule;
 }
 
-public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+	// TOOD: BETA_JAVA9 - Should really check for packages with the module context
 	if (!isPackage(qualifiedPackageName)) return null; // most common case
 
 	try {
 		IBinaryType reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
 		if (reader != null) {
+			char[] modName = this.module == null ? null : this.module.name();
+			if (reader instanceof ClassFileReader) {
+				ClassFileReader classReader = (ClassFileReader) reader;
+				if (classReader.moduleName == null) {
+					classReader.moduleName = modName;
+				}
+			}
 			String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
 			if (this.externalAnnotationPath != null) {
 				try {
@@ -193,7 +266,9 @@
 			}
 			if (this.accessRuleSet == null)
 				return new NameEnvironmentAnswer(reader, null);
-			return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
+			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
@@ -221,8 +296,10 @@
 			}
 			this.zipFile = new ZipFile(this.zipFilename);
 			this.closeZipFileAtEnd = true;
+			this.knownPackageNames = findPackageSet();
+		} else {
+			this.knownPackageNames = findPackageSet();
 		}
-		this.knownPackageNames = findPackageSet(this);
 	} catch(Exception e) {
 		this.knownPackageNames = new SimpleSet(); // assume for this build the zipFile is empty
 	}
@@ -249,4 +326,39 @@
 	return this.zipFilename + '(' + (new Date(time)) + " : " + time + ')'; //$NON-NLS-1$
 }
 
+@Override
+public IModule getModule() {
+	//
+	return this.module;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironment() {
+	//
+	return this;
+}
+
+@Override
+public ITypeLookup typeLookup() {
+	// 
+	return this::findClass;
+}
+
+@Override
+public IPackageLookup packageLookup() {
+	//
+	return this::isPackage;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+	//
+	return this.module == mod ? this : null;
+}
+
+@Override
+public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	// 
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false);
+}
 }
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
new file mode 100644
index 0000000..276b14f
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IMultiModuleEntry;
+import org.eclipse.jdt.internal.compiler.env.IMultiModulePackageLookup;
+import org.eclipse.jdt.internal.compiler.env.IMultiModuleTypeLookup;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+
+public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry {
+
+//private HashMap<String, SimpleSet> packagesInModule = null;
+private static HashMap<String, HashMap<String, SimpleSet>> PackageCache = new HashMap<>();
+private static HashMap<String, Set<IModule>> ModulesCache = new HashMap<>();
+INameEnvironment env = null;
+private String externalAnnotationPath;
+private ZipFile annotationZipFile;
+String zipFilename; // keep for equals
+
+protected Function<char[], ITypeLookup> typeLookupForModule = modName -> 
+(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly) -> {
+return typeLookup().findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly, modName);
+};
+
+protected Function<char[], IPackageLookup> pkgLookupForModule = modName -> 
+qualifiedPackageName -> {
+return packageLookup().isPackage(qualifiedPackageName, modName);
+};
+
+public ClasspathJrt(String zipFilename, IPath externalAnnotationPath, INameEnvironment env) {
+	this.zipFilename = zipFilename;
+	this.env = env;
+	if (externalAnnotationPath != null)
+		this.externalAnnotationPath = externalAnnotationPath.toString();
+	loadModules(this);
+}
+/**
+ * Calculate and cache the package list available in the zipFile.
+ * @param jrt The ClasspathJar to use
+ * @return A SimpleSet with the all the package names in the zipFile.
+ */
+static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrt jrt) {
+	String zipFileName = jrt.zipFilename;
+	HashMap<String, SimpleSet> cache = PackageCache.get(zipFileName);
+	if (cache != null) {
+		return cache;
+	}
+	final HashMap<String, SimpleSet> packagesInModule = new HashMap<>();
+	PackageCache.put(zipFileName, packagesInModule);
+	try {
+		final File imageFile = new File(zipFileName);
+		org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, 
+				new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+			SimpleSet packageSet = null;
+			@Override
+			public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) throws IOException {
+				ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true);
+				return FileVisitResult.CONTINUE;
+			}
+
+			@Override
+			public FileVisitResult visitFile(Path file, Path mod, BasicFileAttributes attrs) throws IOException {
+				return FileVisitResult.CONTINUE;
+			}
+
+			@Override
+			public FileVisitResult visitModule(Path mod) throws IOException {
+				String name = mod.toString();
+				try {
+					jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModuleEnvironment.MODULE_INFO_CLASS, name));
+				} catch (ClassFormatException e) {
+					e.printStackTrace();
+				}
+				this.packageSet = new SimpleSet(41);
+				this.packageSet.add(""); //$NON-NLS-1$
+				packagesInModule.put(name, this.packageSet);
+				return FileVisitResult.CONTINUE;
+			}
+		}, JRTUtil.NOTIFY_PACKAGES | JRTUtil.NOTIFY_MODULES);
+	} catch (IOException e) {
+		// TODO: BETA_JAVA9 Should report better
+	}
+	return packagesInModule;
+}
+
+public static void loadModules(final ClasspathJrt jrt) {
+	String zipFileName = jrt.zipFilename;
+	Set<IModule> cache = ModulesCache.get(zipFileName);
+
+	if (cache == null) {
+		try {
+			final File imageFile = new File(zipFileName);
+			org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile,
+					new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+				SimpleSet packageSet = null;
+
+				@Override
+				public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs)
+						throws IOException {
+					ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true);
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitFile(Path file, Path mod, BasicFileAttributes attrs)
+						throws IOException {
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitModule(Path mod) throws IOException {
+					try {
+						jrt.acceptModule(JRTUtil.getClassfileContent(imageFile, IModuleEnvironment.MODULE_INFO_CLASS, mod.toString()));
+					} catch (ClassFormatException e) {
+						e.printStackTrace();
+					}
+					return FileVisitResult.SKIP_SUBTREE;
+				}
+			}, JRTUtil.NOTIFY_MODULES);
+		} catch (IOException e) {
+			// TODO: BETA_JAVA9 Should report better
+		}
+	} else {
+//		for (IModuleDeclaration iModule : cache) {
+//			jimage.env.acceptModule(iModule, jimage);
+//		}
+	}
+}
+void acceptModule(byte[] content) {
+	if (content == null) 
+		return;
+	ClassFileReader reader = null;
+	try {
+		reader = new ClassFileReader(content, IModuleEnvironment.MODULE_INFO_CLASS.toCharArray(), null);
+	} catch (ClassFormatException e) {
+		e.printStackTrace();
+	}
+	if (reader != null) {
+		IModule moduleDecl = reader.getModuleDeclaration();
+		if (moduleDecl != null) {
+			Set<IModule> cache = ModulesCache.get(this.zipFilename);
+			if (cache == null) {
+				ModulesCache.put(this.zipFilename, cache = new HashSet<IModule>());
+			}
+			cache.add(moduleDecl);
+		}
+	}
+}
+public void cleanup() {
+	if (this.annotationZipFile != null) {
+		try {
+			this.annotationZipFile.close();
+		} catch(IOException e) { // ignore it
+		}
+		this.annotationZipFile = null;
+	}
+}
+
+public boolean equals(Object o) {
+	if (this == o) return true;
+	if (!(o instanceof ClasspathJrt)) return false;
+	ClasspathJrt jar = (ClasspathJrt) o;
+	return this.zipFilename.endsWith(jar.zipFilename);
+}
+
+private NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, Optional<Collection<char[]>> moduleNames) {
+	if (!isPackage(qualifiedPackageName)) return null; // most common case
+
+	try {
+		IBinaryType reader = ClassFileReader.readFromModules(new File(this.zipFilename), qualifiedBinaryFileName, moduleNames);
+		if (reader != null) {
+			if (this.externalAnnotationPath != null) {
+				String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+				try {
+					if (this.annotationZipFile == null) {
+						this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(this.externalAnnotationPath, null);
+					}
+					reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath, fileNameWithoutExtension, this.annotationZipFile);
+				} catch (IOException e) {
+					// don't let error on annotations fail class reading
+				}
+			}
+			return new NameEnvironmentAnswer(reader, null, reader.getModule());
+		}
+	} catch (IOException e) { // treat as if class file is missing
+	} catch (ClassFormatException e) { // treat as if class file is missing
+	}
+	return null;
+}
+
+public IPath getProjectRelativePath() {
+	return null;
+}
+
+public int hashCode() {
+	return this.zipFilename == null ? super.hashCode() : this.zipFilename.hashCode();
+}
+@Override
+public boolean isPackage(String qualifiedPackageName) {
+	//
+	return isPackage(qualifiedPackageName, Optional.empty());
+}
+public boolean isPackage(String qualifiedPackageName, Optional<char[]> moduleName) {
+//	try {
+//		synchronized (this) {
+//			if (this.packagesInModule == null) {
+//				this.packagesInModule = findPackagesInModules(this);
+//			}
+//		}
+//	} catch(Exception e) {
+//		// TODO BETA_JAVA9
+//	}
+//	if (moduleName.isPresent()) {
+//		SimpleSet set = this.packagesInModule.get(moduleName.get());
+//		return set != null && set.includes(qualifiedPackageName);
+//	}
+//	Set<String> keySet = this.packagesInModule.keySet();
+//	for (String string : keySet) {
+//		SimpleSet set = this.packagesInModule.get(string);
+//		if (set.includes(qualifiedPackageName)) return true;
+//	}
+//
+//	return false;
+	return JRTUtil.isPackage(new File(this.zipFilename), qualifiedPackageName, moduleName);
+}
+
+public String toString() {
+	String start = "Classpath jrt file " + this.zipFilename; //$NON-NLS-1$
+	return start;
+}
+
+public String debugPathString() {
+	return this.zipFilename;
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly, Optional<Collection<char[]>> moduleNames) {
+	String fileName = new String(typeName);
+	return findClass(fileName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly, Optional.empty());
+}
+@Override
+public IModule getModule(char[] moduleName) {
+	Set<IModule> modules = ModulesCache.get(this.zipFilename);
+	if (modules != null) {
+		for (IModule mod : modules) {
+			if (CharOperation.equals(mod.name(), moduleName))
+					return mod;
+		}
+	}
+	return null;
+}
+@Override
+public IMultiModuleTypeLookup typeLookup() {
+	return this::findClass;
+}
+@Override
+public IMultiModulePackageLookup packageLookup() {
+	return this::isPackage;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironment() {
+	//
+	return this;
+}
+@Override
+public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+	// 
+	return new IModuleEnvironment() {
+		
+		@Override
+		public ITypeLookup typeLookup() {
+			//
+			return servesModule(mod.name()) ? ClasspathJrt.this.typeLookupForModule.apply(mod.name()) : ITypeLookup.Dummy;
+		}
+		
+		@Override
+		public IPackageLookup packageLookup() {
+			//
+			return servesModule(mod.name()) ? ClasspathJrt.this.pkgLookupForModule.apply(mod.name()) : IPackageLookup.Dummy;
+		}
+	};
+}
+@Override
+public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+	// 
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, false, Optional.empty());
+}
+@Override
+public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName,
+		boolean asBinaryOnly) {
+	//
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly, Optional.empty());
+}
+
+}
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 8758a86..f1fc8ff 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -12,44 +16,70 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.builder;
 
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
-public abstract class ClasspathLocation {
+public abstract class ClasspathLocation implements IModuleEnvironment {
 
-static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
-	return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, ignoreOptionalProblems);
+	protected boolean isAutoModule;
+	protected IModule module;
+	abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
+	abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly);
+	abstract public boolean isPackage(String qualifiedPackageName);
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		String fileName = new String(typeName);
+		return findClass(fileName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
+	}
+	public void setModule (IModule mod) {
+		this.module = mod;
+	}
+	static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder,
+			char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems,
+			INameEnvironment env) {
+		return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns,
+				ignoreOptionalProblems, env);
+	}
+public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, INameEnvironment env, boolean autoModule) {
+	return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath, env, autoModule);
 }
 
-public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
-	return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath);
+static ClasspathLocation forLibrary(String libraryPathname, 
+										long lastModified, 
+										AccessRuleSet accessRuleSet, 
+										IPath annotationsPath,
+										INameEnvironment env,
+										boolean autoModule) {
+	return Util.isJrt(libraryPathname) ?
+			new ClasspathJrt(libraryPathname, annotationsPath, env) :
+				Util.archiveFormat(libraryPathname) == Util.JMOD_FILE ?
+					new ClasspathJMod(libraryPathname, lastModified, accessRuleSet, annotationsPath, env) :
+			new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, env, false);
+
 }
 
-static ClasspathLocation forLibrary(String libraryPathname, long lastModified, AccessRuleSet accessRuleSet, IPath annotationsPath) {
-	return new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath);
+public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath,
+											INameEnvironment env, boolean autoModule) {
+	return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath, env, autoModule);
 }
 
-static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath) {
-	return forLibrary(libraryPathname, 0, accessRuleSet, annotationsPath);
+static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath,
+										INameEnvironment env, boolean autoModule) {
+	return new ClasspathJar(library, accessRuleSet, annotationsPath, env, autoModule);
 }
 
-static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath) {
-	return new ClasspathJar(library, accessRuleSet, annotationsPath);
-}
-
-public abstract NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName);
-
 public abstract IPath getProjectRelativePath();
 
 public boolean isOutputFolder() {
 	return false;
 }
 
-public abstract boolean isPackage(String qualifiedPackageName);
-
 public void cleanup() {
 	// free anything which is not required when the state is saved
 }
@@ -59,4 +89,20 @@
 
 public abstract String debugPathString();
 
+void acceptModule(IModule mod) {
+	if (mod != null) {
+		this.module = mod;
+	}
+}
+public IModule getModule() {
+	return this.module;
+}
+/**
+ * Specifies whether this entry represents an automatic module.
+ * 
+ * @return true if this is an automatic module, false otherwise
+ */
+public boolean isAutomaticModule() {
+	return this.isAutoModule;
+}
 }
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 991e98e..4278164 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
@@ -5,14 +5,24 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.builder;
 
 import org.eclipse.core.resources.*;
-
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.core.ModuleInfo;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public class ClasspathMultiDirectory extends ClasspathDirectory {
@@ -23,8 +33,8 @@
 boolean hasIndependentOutputFolder; // if output folder is not equal to any of the source folders
 public boolean ignoreOptionalProblems;
 
-ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
-	super(binaryFolder, true, null, null);
+ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems, INameEnvironment env) {
+	super(binaryFolder, true, null, null, env, false /* source never an automatic module*/);
 
 	this.sourceFolder = sourceFolder;
 	this.inclusionPatterns = inclusionPatterns;
@@ -44,6 +54,10 @@
 	if (!(o instanceof ClasspathMultiDirectory)) return false;
 
 	ClasspathMultiDirectory md = (ClasspathMultiDirectory) o;
+	// TODO: revisit this - is this really required??
+//	if (this.module != md.module)
+//		if (this.module == null || !this.module.equals(md.module))
+//			return false;
 	return this.ignoreOptionalProblems == md.ignoreOptionalProblems 
 		&& this.sourceFolder.equals(md.sourceFolder) && this.binaryFolder.equals(md.binaryFolder)
 		&& CharOperation.equals(this.inclusionPatterns, md.inclusionPatterns)
@@ -61,4 +75,24 @@
 	return "Source classpath directory " + this.sourceFolder.getFullPath().toString() + //$NON-NLS-1$
 		" with " + super.toString(); //$NON-NLS-1$
 }
+
+public void acceptModuleInfo(ICompilationUnit cu, Parser parser) {
+	CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10);
+	CompilationUnitDeclaration unit = parser.parse(cu, compilationResult);
+	// Request could also come in when module-info has changed or removed.
+	if (unit.isModuleInfo() && unit.moduleDeclaration != null) {
+		IModule decl = ModuleInfo.createModule(unit.moduleDeclaration);
+		if (decl != null) {
+			this.module = decl;
+		}
+	}
+}
+public void setModule(IModule mod) {
+	this.module = mod;
+}
+
+public IModule module() {
+	return this.module;
+}
+
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 5268a08..4dfe3d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -82,7 +86,7 @@
 
 		this.notifier.subTask(Messages.build_analyzingDeltas);
 		if (this.javaBuilder.hasBuildpathErrors()) {
-			// if a mssing class file was detected in the last build, a build state was saved since its no longer fatal
+			// if a missing class file was detected in the last build, a build state was saved since its no longer fatal
 			// but we need to rebuild every source file since problems were not recorded
 			// AND to avoid the infinite build scenario if this project is involved in a cycle, see bug 160550
 			// we need to avoid unnecessary deltas caused by doing a full build in this case
@@ -598,6 +602,7 @@
 						if (JavaBuilder.DEBUG)
 							System.out.println("Compile this added source file " + typeLocator); //$NON-NLS-1$
 						this.sourceFiles.add(new SourceFile((IFile) resource, md, true));
+						this.sourceFiles.add(new SourceFile((IFile) resource, md, true));
 						String typeName = typePath.toString();
 						if (!this.newState.isDuplicateLocator(typeName, typeLocator)) { // adding dependents results in 2 duplicate errors
 							if (JavaBuilder.DEBUG)
@@ -635,7 +640,8 @@
 							return true; // skip it since it really isn't changed
 						if (JavaBuilder.DEBUG)
 							System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$
-						this.sourceFiles.add(new SourceFile((IFile) resource, md, true));
+						SourceFile unit = new SourceFile((IFile) resource, md, true);
+						this.sourceFiles.add(unit);
 				}
 				return true;
 			} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resourceName)) {
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
new file mode 100644
index 0000000..66cb934
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.util.stream.Stream;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
+
+/**
+ * Represents a project on the module path.
+ */
+public class ModulePathEntry implements IModulePathEntry {
+
+	private IPath path;
+	/*private*/ ClasspathLocation[] locations;
+	IModule module;
+	IModuleEnvironment env = null;
+
+	class ModuleEnvironment implements IModuleEnvironment {
+		@Override
+		public ITypeLookup typeLookup() {
+			//
+			return Stream.of(ModulePathEntry.this.locations).map(loc -> loc.typeLookup()).reduce(ITypeLookup::chain).orElse(ITypeLookup.Dummy);
+		}
+
+		@Override
+		public IPackageLookup packageLookup() {
+			// 
+			return name -> Stream.of(ModulePathEntry.this.locations).map(loc -> loc.packageLookup()).anyMatch(p -> p.isPackage(name));
+		}
+	}
+
+	ModulePathEntry(IPath path, IModule module, ClasspathLocation[] locations) {
+		this.path = path;
+		this.locations = locations;
+		this.module = module;
+		initializeModule();
+	}
+	public IPath getPath() {
+		return this.path;
+	}
+	public ClasspathLocation[] getClasspathLocations() {
+		return this.locations;
+	}
+
+	@Override
+	public IModule getModule() {
+		//
+		return this.module;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironment() {
+		//
+		if (this.env == null)
+			this.env = new ModuleEnvironment();
+		return this.env;
+	}
+
+	@Override
+	public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+		//
+		if (this.module.equals(mod)) {
+			return getLookupEnvironment();
+		}
+		return null;
+	}
+	// TODO: This is only needed because SourceFile.module() uses the module set on the location
+	// Once we have a mechanism to map a folder to a module path entry, this should no longer be
+	// needed
+	private void initializeModule() {
+		for (int i = 0; i < this.locations.length; i++) {
+			this.locations[i].setModule(this.module);
+		}
+	}
+}
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 c1509e1..deffd77 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Terry Parker <tparker@google.com> 
@@ -22,21 +26,26 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleEnvironment;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.*;
 
 import java.io.*;
 import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @SuppressWarnings({"rawtypes", "unchecked"})
-public class NameEnvironment implements INameEnvironment, SuffixConstants {
+public class NameEnvironment extends ModuleEnvironment implements SuffixConstants {
 
 boolean isIncrementalBuild;
 ClasspathMultiDirectory[] sourceLocations;
 ClasspathLocation[] binaryLocations;
+IModulePathEntry[] modulePathEntries;
 BuildNotifier notifier;
 
 SimpleSet initialTypeNames; // assumed that each name is of the form "a/b/ClassName"
@@ -100,6 +109,9 @@
 	IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath();
 	ArrayList sLocations = new ArrayList(classpathEntries.length);
 	ArrayList bLocations = new ArrayList(classpathEntries.length);
+	List<IModulePathEntry> entries = new ArrayList<>(classpathEntries.length);
+	IModuleDescription mod = null;
+	
 	nextEntry : for (int i = 0, l = classpathEntries.length; i < l; i++) {
 		ClasspathEntry entry = (ClasspathEntry) classpathEntries[i];
 		IPath path = entry.getPath();
@@ -121,8 +133,13 @@
 					if (!outputFolder.exists())
 						createOutputFolder(outputFolder);
 				}
-				sLocations.add(
-					ClasspathLocation.forSourceFolder((IContainer) target, outputFolder, entry.fullInclusionPatternChars(), entry.fullExclusionPatternChars(), entry.ignoreOptionalProblems()));
+					sLocations.add(ClasspathLocation.forSourceFolder(
+							(IContainer) target, 
+							outputFolder,
+							entry.fullInclusionPatternChars(), 
+							entry.fullExclusionPatternChars(),
+							entry.ignoreOptionalProblems(),
+							this));
 				continue nextEntry;
 
 			case IClasspathEntry.CPE_PROJECT :
@@ -133,6 +150,7 @@
 				JavaProject prereqJavaProject = (JavaProject) JavaCore.create(prereqProject);
 				IClasspathEntry[] prereqClasspathEntries = prereqJavaProject.getRawClasspath();
 				ArrayList seen = new ArrayList();
+				List<ClasspathLocation> projectLocations = new ArrayList<ClasspathLocation>();
 				nextPrereqEntry: for (int j = 0, m = prereqClasspathEntries.length; j < m; j++) {
 					IClasspathEntry prereqEntry = prereqClasspathEntries[j];
 					if (prereqEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
@@ -146,8 +164,9 @@
 							: (IContainer) root.getFolder(prereqOutputPath);
 						if (binaryFolder.exists() && !seen.contains(binaryFolder)) {
 							seen.add(binaryFolder);
-							ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet(), externalAnnotationPath);
+							ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet(), externalAnnotationPath, this, entry.isAutomaticModule());
 							bLocations.add(bLocation);
+							projectLocations.add(bLocation);
 							if (binaryLocationsPerProject != null) { // normal builder mode
 								ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(prereqProject);
 								if (existingLocations == null) {
@@ -162,6 +181,11 @@
 						}
 					}
 				}
+				if ((mod = prereqJavaProject.getModuleDescription()) != null && projectLocations.size() > 0) {
+					ModuleDescriptionInfo info = (ModuleDescriptionInfo) ((SourceModule)mod).getElementInfo();
+					ModulePathEntry projectEntry = new ModulePathEntry(prereqJavaProject.getPath(), info, projectLocations.toArray(new ClasspathLocation[projectLocations.size()]));
+					entries.add(projectEntry);
+				}
 				continue nextEntry;
 
 			case IClasspathEntry.CPE_LIBRARY :
@@ -174,16 +198,21 @@
 							&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
 								? null
 								: entry.getAccessRuleSet();
-						bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath);
+						bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath, this, entry.isAutomaticModule());
 					} else if (resource instanceof IContainer) {
 						AccessRuleSet accessRuleSet =
 							(JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
 							&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
 								? null
 								: entry.getAccessRuleSet();
-						bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet, externalAnnotationPath);	 // is library folder not output folder
+						bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet, externalAnnotationPath, this, entry.isAutomaticModule());	 // is library folder not output folder
 					}
 					bLocations.add(bLocation);
+					// TODO: Ideally we need to do something like mapToModulePathEntry using the path and if it is indeed
+					// a module path entry, then add the corresponding entry here, but that would need the target platform
+					if (bLocation instanceof IModulePathEntry) {
+						entries.add((IModulePathEntry) bLocation);
+					}
 					if (binaryLocationsPerProject != null) { // normal builder mode
 						IProject p = resource.getProject(); // can be the project being built
 						ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(p);
@@ -202,7 +231,13 @@
 							&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
 								? null
 								: entry.getAccessRuleSet();
-					bLocations.add(ClasspathLocation.forLibrary(path.toString(), accessRuleSet, externalAnnotationPath));
+					ClasspathLocation bLocation = ClasspathLocation.forLibrary(path.toOSString(), accessRuleSet, externalAnnotationPath, this, entry.isAutomaticModule());
+					bLocations.add(bLocation);
+					// TODO: Ideally we need to do something like mapToModulePathEntry using the path and if it is indeed
+					// a module path entry, then add the corresponding entry here, but that would need the target platform
+					if (bLocation instanceof IModulePathEntry) {
+						entries.add((IModulePathEntry) bLocation);
+					}
 				}
 				continue nextEntry;
 		}
@@ -213,7 +248,11 @@
 	this.sourceLocations = new ClasspathMultiDirectory[sLocations.size()];
 	if (!sLocations.isEmpty()) {
 		sLocations.toArray(this.sourceLocations);
-
+		if ((mod = javaProject.getModuleDescription()) != null) {
+			ModuleDescriptionInfo info = (ModuleDescriptionInfo) ((SourceModule)mod).getElementInfo();
+			ModulePathEntry projectEntry = new ModulePathEntry(javaProject.getPath(), info, this.sourceLocations);
+			entries.add(0, projectEntry);
+		}
 		// collect the output folders, skipping duplicates
 		next : for (int i = 0, l = this.sourceLocations.length; i < l; i++) {
 			ClasspathMultiDirectory md = this.sourceLocations[i];
@@ -241,6 +280,8 @@
 		this.binaryLocations[index++] = (ClasspathLocation) outputFolders.get(i);
 	for (int i = 0, l = bLocations.size(); i < l; i++)
 		this.binaryLocations[index++] = (ClasspathLocation) bLocations.get(i);
+	
+	this.modulePathEntries = entries.toArray(new IModulePathEntry[entries.size()]);
 }
 
 public void cleanup() {
@@ -250,6 +291,7 @@
 		this.sourceLocations[i].cleanup();
 	for (int i = 0, l = this.binaryLocations.length; i < l; i++)
 		this.binaryLocations[i].cleanup();
+	this.modulePathEntries = null;
 }
 
 private void createOutputFolder(IContainer outputFolder) throws CoreException {
@@ -264,7 +306,7 @@
 	}
 }
 
-private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, IModuleContext moduleContext) {
 	if (this.notifier != null)
 		this.notifier.checkCancelWithinCompiler();
 
@@ -296,59 +338,72 @@
 	}
 
 	String qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
-	String binaryFileName = qBinaryFileName;
-	String qPackageName =  ""; //$NON-NLS-1$
-	if (qualifiedTypeName.length() > typeName.length) {
-		int typeNameStart = qBinaryFileName.length() - typeName.length - 6; // size of ".class"
-		qPackageName =  qBinaryFileName.substring(0, typeNameStart - 1);
-		binaryFileName = qBinaryFileName.substring(typeNameStart);
+	String qPackageName =  (qualifiedTypeName.length() == typeName.length) ? Util.EMPTY_STRING :
+		qBinaryFileName.substring(0, qBinaryFileName.length() - typeName.length - 7);
+	char[] binaryFileName = CharOperation.concat(typeName, SUFFIX_class);
+	if (IModuleContext.UNNAMED_MODULE_CONTEXT == moduleContext) {
+		return Stream.of(this.binaryLocations)
+				.map(p -> p.typeLookup())
+				.reduce(ITypeLookup::chain)
+				.map(t -> t.findClass(binaryFileName, qPackageName, qBinaryFileName)).orElse(null);
 	}
+	NameEnvironmentAnswer answer = moduleContext.getEnvironment().map(env -> env.typeLookup())
+				.reduce(ITypeLookup::chain)
+				.map(lookup -> lookup.findClass(binaryFileName, qPackageName, qBinaryFileName))
+				.orElse(null);
+	if (answer != null)
+		return answer;
+	
+	return Stream.of(this.modulePathEntries).filter(mod ->
+				(mod instanceof ClasspathLocation && ((ClasspathLocation) mod).isAutoModule))
+			.map(p -> p.getLookupEnvironment().typeLookup())
+			.reduce(ITypeLookup::chain)
+			.map(t -> t.findClass(binaryFileName, qPackageName, qBinaryFileName)).orElse(null);
 
-	// NOTE: the output folders are added at the beginning of the binaryLocations
-	NameEnvironmentAnswer suggestedAnswer = null;
-	for (int i = 0, l = this.binaryLocations.length; i < l; i++) {
-		NameEnvironmentAnswer answer = this.binaryLocations[i].findClass(binaryFileName, qPackageName, qBinaryFileName);
-		if (answer != null) {
-			if (!answer.ignoreIfBetter()) {
-				if (answer.isBetter(suggestedAnswer))
-					return answer;
-			} else if (answer.isBetter(suggestedAnswer))
-				// remember suggestion and keep looking
-				suggestedAnswer = answer;
-		}
-	}
-	if (suggestedAnswer != null)
-		// no better answer was found
-		return suggestedAnswer;
-	return null;
 }
 
 public NameEnvironmentAnswer findType(char[][] compoundName) {
 	if (compoundName != null)
 		return findClass(
 			new String(CharOperation.concatWith(compoundName, '/')),
-			compoundName[compoundName.length - 1]);
+			compoundName[compoundName.length - 1], IModuleContext.UNNAMED_MODULE_CONTEXT);
 	return null;
 }
-
+public NameEnvironmentAnswer findType(char[][] compoundName, IModuleContext context) {
+	if (compoundName != null)
+		return findClass(
+			new String(CharOperation.concatWith(compoundName, '/')),
+			compoundName[compoundName.length - 1], context);
+	return null;
+}
 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
 	if (typeName != null)
 		return findClass(
 			new String(CharOperation.concatWith(packageName, typeName, '/')),
-			typeName);
+			typeName, IModuleContext.UNNAMED_MODULE_CONTEXT);
 	return null;
 }
-
-public boolean isPackage(char[][] compoundName, char[] packageName) {
-	return isPackage(new String(CharOperation.concatWith(compoundName, packageName, '/')));
+public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext context) {
+	if (typeName != null)
+		return findClass(
+			new String(CharOperation.concatWith(packageName, typeName, '/')),
+			typeName, context);
+	return null;
 }
-
+public boolean isPackage(char[][] compoundName, char[] packageName, IModuleContext moduleContext) {
+	return isPackage(new String(CharOperation.concatWith(compoundName, packageName, '/')), moduleContext);
+}
 public boolean isPackage(String qualifiedPackageName) {
-	// NOTE: the output folders are added at the beginning of the binaryLocations
-	for (int i = 0, l = this.binaryLocations.length; i < l; i++)
-		if (this.binaryLocations[i].isPackage(qualifiedPackageName))
-			return true;
-	return false;
+	return isPackage(qualifiedPackageName, IModuleContext.UNNAMED_MODULE_CONTEXT);
+}
+public boolean isPackage(String qualifiedPackageName, IModuleContext moduleContext) {
+	if (moduleContext == IModuleContext.UNNAMED_MODULE_CONTEXT) {
+		return Stream.of(this.binaryLocations).map(p -> p.packageLookup())
+				.filter(l -> l.isPackage(qualifiedPackageName)).findAny().isPresent();
+	} else {
+		return moduleContext.getEnvironment().map(e -> e.packageLookup())
+				.filter(l -> l.isPackage(qualifiedPackageName)).findAny().isPresent();
+	}
 }
 
 void setNames(String[] typeNames, SourceFile[] additionalFiles) {
@@ -377,4 +432,33 @@
 	for (int i = 0, l = this.binaryLocations.length; i < l; i++)
 		this.binaryLocations[i].reset();
 }
+
+@Override
+public IModule getModule(char[] name) {
+	if (name == null)
+		return null;
+	IModule module = null;
+	for (int i = 0; i < this.modulePathEntries.length; i++) {
+		if ((module = this.modulePathEntries[i].getModule(name)) != null)
+			break;
+	}
+	return module;
+}
+public IModuleEnvironment getModuleEnvironmentFor(char[] moduleName) {
+	IModule module = null;
+	for (int i = 0; i < this.modulePathEntries.length; i++) {
+		if ((module = this.modulePathEntries[i].getModule(moduleName)) != null)
+			return this.modulePathEntries[i].getLookupEnvironmentFor(module);
+	}
+	return null;
+}
+@Override
+public IModule[] getAllAutomaticModules() {
+	if (this.modulePathEntries == null)
+		return IModule.NO_MODULES;
+	Set<IModule> set = Stream.of(this.modulePathEntries).map(e -> e.getModule()).filter(m -> m.isAutomatic())
+			.collect(Collectors.toSet());
+	return set.toArray(new IModule[set.size()]);
+}
+
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
index 4a5b04d..1c9d5cf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -16,6 +20,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IModule;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -114,4 +119,10 @@
 	return "SourceFile[" //$NON-NLS-1$
 		+ this.resource.getFullPath() + "]";  //$NON-NLS-1$
 }
+
+@Override
+public char[] module() {
+	IModule mod = this.sourceLocation.module();
+	return mod == null ? null : mod.name();
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index f7fb9fb..4bc15a6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -17,8 +21,10 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.AccessRule;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.ClasspathAccessRule;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 
@@ -32,6 +38,7 @@
 String javaProjectName;
 public ClasspathMultiDirectory[] sourceLocations;
 ClasspathLocation[] binaryLocations;
+INameEnvironment environment;
 // keyed by the project relative path of the type (i.e. "src1/p1/p2/A.java"), value is a ReferenceCollection or an AdditionalTypeCollection
 SimpleLookupTable references;
 // keyed by qualified type name "p1/p2/A", value is the project relative path which defines this type "src1/p1/p2/A.java"
@@ -47,7 +54,7 @@
 private StringSet structurallyChangedTypes;
 public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
 
-public static final byte VERSION = 0x001D;
+public static final byte VERSION = 0x001E;
 
 static final byte SOURCE_FOLDER = 1;
 static final byte BINARY_FOLDER = 2;
@@ -63,6 +70,7 @@
 	this.previousStructuralBuildTime = -1;
 	this.structurallyChangedTypes = null;
 	this.javaProjectName = javaBuilder.currentProject.getName();
+	this.environment = javaBuilder.nameEnvironment;
 	this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations;
 	this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
 	this.references = new SimpleLookupTable(7);
@@ -249,7 +257,7 @@
 		if ((folderName = in.readUTF()).length() > 0) sourceFolder = project.getFolder(folderName);
 		if ((folderName = in.readUTF()).length() > 0) outputFolder = project.getFolder(folderName);
 		ClasspathMultiDirectory md =
-			(ClasspathMultiDirectory) ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, readNames(in), readNames(in), in.readBoolean());
+			(ClasspathMultiDirectory) ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, readNames(in), readNames(in), in.readBoolean(), newState.environment);
 		if (in.readBoolean())
 			md.hasIndependentOutputFolder = true;
 		newState.sourceLocations[i] = md;
@@ -268,13 +276,17 @@
 				IContainer outputFolder = path.segmentCount() == 1
 					? (IContainer) root.getProject(path.toString())
 					: (IContainer) root.getFolder(path);
-				newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), readRestriction(in), new Path(in.readUTF()));
+					newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(),
+							readRestriction(in), new Path(in.readUTF()), newState.environment, in.readBoolean());
 				break;
 			case EXTERNAL_JAR :
-				newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF(), in.readLong(), readRestriction(in), new Path(in.readUTF()));
+				String jarPath = in.readUTF();
+				newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
+							readRestriction(in), new Path(in.readUTF()), newState.environment, Util.isJrt(jarPath) ? false : in.readBoolean());
 				break;
 			case INTERNAL_JAR :
-				newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), readRestriction(in), new Path(in.readUTF()));
+					newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
+							readRestriction(in), new Path(in.readUTF()), newState.environment, in.readBoolean());
 		}
 	}
 
@@ -455,7 +467,8 @@
 			out.writeBoolean(cd.isOutputFolder);
 			writeRestriction(cd.accessRuleSet, out);
 			out.writeUTF(cd.externalAnnotationPath != null ? cd.externalAnnotationPath : ""); //$NON-NLS-1$
-		} else {
+			out.writeBoolean(cd.isAutomaticModule());
+		} else if (c instanceof ClasspathJar) {
 			ClasspathJar jar = (ClasspathJar) c;
 			if (jar.resource == null) {
 				out.writeByte(EXTERNAL_JAR);
@@ -467,6 +480,14 @@
 			}
 			writeRestriction(jar.accessRuleSet, out);
 			out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$
+			out.writeBoolean(jar.isAutomaticModule());
+		} else {
+			ClasspathJrt jrt = (ClasspathJrt) c;
+			out.writeByte(EXTERNAL_JAR);
+			out.writeUTF(jrt.zipFilename);
+			out.writeLong(-1);
+			writeRestriction(null, out);
+			out.writeUTF(""); //$NON-NLS-1$
 		}
 	}
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
index 0427355..a6d173c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -301,6 +305,11 @@
 	return walker;
 }
 @Override
+public char[] getModule() {
+	// TODO BETA_JAVA9 Auto-generated method stub
+	return null;
+}
+@Override
 public ExternalAnnotationStatus getExternalAnnotationStatus() {
 	return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
 }
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 c13de15..a6ac57d 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
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -273,15 +277,15 @@
 /**
  * Create an ICompilationUnit info from the given compilation unit on disk.
  */
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
-	final char[] elementName = handle.getElementName().toCharArray();
-	return new ResourceCompilationUnit(file) {
-		@Override
-		public char[] getFileName() {
-			return elementName;
-		}
-	};
-}
+	protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
+		final char[] elementName = handle.getElementName().toCharArray();
+		return new ResourceCompilationUnit(file, null) {
+			@Override
+			public char[] getFileName() {
+				return elementName;
+			}
+		};
+	}
 	/**
  * Creates the type info from the given class file on disk and
  * adds it to the given list of infos.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index f232f66..03609fb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - contribution for Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
@@ -831,7 +835,6 @@
 						parsedUnit.scope.faultInTypes();
 						parsedUnit.resolve();
 					}
-					
 					rememberAllTypes(parsedUnit, cus[i], containsLocalType);
 				}
 			}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index a81cfe6..2a4c03d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -234,7 +238,8 @@
 				// top level or member type
 				if (!inProjectOfFocusType) {
 					char[] typeQualifiedName = focusType.getTypeQualifiedName('.').toCharArray();
-					String[] packageName = ((PackageFragment) focusType.getPackageFragment()).names;
+					PackageFragment fragment = (PackageFragment) focusType.getPackageFragment();
+					String[] packageName = fragment.names;
 					if (searchableEnvironment.findType(typeQualifiedName, Util.toCharArrays(packageName)) == null) {
 						// focus type is not visible in this project: no need to go further
 						return;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
index c00aa48..3855810 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -57,4 +61,9 @@
 public String toString() {
 	return "CompilationUnit[" + new String(this.fFileName) + "]";  //$NON-NLS-2$ //$NON-NLS-1$
 }
+@Override
+public char[] module() {
+	// TODO BETA_JAVA9 Auto-generated method stub
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java
index 19629a2..4eeef5a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DOMFinder.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contributions for
@@ -35,6 +39,7 @@
 import org.eclipse.jdt.core.dom.LambdaExpression;
 import org.eclipse.jdt.core.dom.MarkerAnnotation;
 import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.ModuleDeclaration;
 import org.eclipse.jdt.core.dom.NormalAnnotation;
 import org.eclipse.jdt.core.dom.PackageDeclaration;
 import org.eclipse.jdt.core.dom.ParameterizedType;
@@ -154,6 +159,12 @@
 		return true;
 	}
 
+	public boolean visit(ModuleDeclaration node) {
+		if (found(node, node.getName()) && this.resolveBinding) {
+			// this.foundBinding = node.resolveBinding(); TODO: Enable after bug 515875 enables module binding
+		}
+		return true;
+	}
 	public boolean visit(NormalAnnotation node) {
 		if (found(node, node) && this.resolveBinding)
 			this.foundBinding = node.resolveAnnotationBinding();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index 39e1896..1e7dd39 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -974,6 +978,8 @@
 				versionNumber = JavaCore.VERSION_1_7;
 			} else if (minorVersion == 0 && majorVersion == 52) {
 				versionNumber = JavaCore.VERSION_1_8;
+			} else if (minorVersion == 0 && majorVersion == 53) {
+				versionNumber = JavaCore.VERSION_9;
 			}
 			buffer.append(
 				Messages.bind(Messages.classfileformat_versiondetails,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
index 94f0a27..18c5a2c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -97,6 +101,12 @@
 				this.packageHandles= new HashtableOfArrayToObject(5);
 			}
 			// create handle
+			String module = null;
+			String rootPath = this.lastPkgFragmentRoot.getPath().toOSString();
+			if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) {
+				module = resourcePath.substring(separatorIndex + 1, 
+						(separatorIndex = resourcePath.lastIndexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR)));
+			}
 			String classFilePath= resourcePath.substring(separatorIndex + 1);
 			String[] simpleNames = new Path(classFilePath).segments();
 			String[] pkgName;
@@ -109,7 +119,7 @@
 			}
 			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName);
 			if (pkgFragment == null) {
-				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(pkgName);
+				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(pkgName, module);
 				this.packageHandles.put(pkgName, pkgFragment);
 			}
 			IClassFile classFile= pkgFragment.getClassFile(simpleNames[length]);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
index 06f26fb..eff8598 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
@@ -23,6 +23,7 @@
 	public static final String COMPILATIONUNIT = Character.toString(JavaElement.JEM_COMPILATIONUNIT);
 	public static final String CLASSFILE = Character.toString(JavaElement.JEM_CLASSFILE);
 	public static final String TYPE = Character.toString(JavaElement.JEM_TYPE);
+	public static final String MODULE = Character.toString(JavaElement.JEM_MODULE);
 	public static final String PACKAGEDECLARATION = Character.toString(JavaElement.JEM_PACKAGEDECLARATION);
 	public static final String IMPORTDECLARATION = Character.toString(JavaElement.JEM_IMPORTDECLARATION);
 	public static final String LOCALVARIABLE = Character.toString(JavaElement.JEM_LOCALVARIABLE);
@@ -92,6 +93,8 @@
 				return CLASSFILE;
 			case JavaElement.JEM_TYPE:
 				return TYPE;
+			case JavaElement.JEM_MODULE:
+				return MODULE;
 			case JavaElement.JEM_PACKAGEDECLARATION:
 				return PACKAGEDECLARATION;
 			case JavaElement.JEM_IMPORTDECLARATION:
@@ -120,6 +123,7 @@
 				case JavaElement.JEM_COMPILATIONUNIT:
 				case JavaElement.JEM_CLASSFILE:
 				case JavaElement.JEM_TYPE:
+				case JavaElement.JEM_MODULE:
 				case JavaElement.JEM_PACKAGEDECLARATION:
 				case JavaElement.JEM_IMPORTDECLARATION:
 				case JavaElement.JEM_LOCALVARIABLE:
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
new file mode 100644
index 0000000..cae7e64
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ModuleUtil.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.BasicCompilationUnit;
+import org.eclipse.jdt.internal.core.builder.NameEnvironment;
+import org.eclipse.jdt.internal.core.builder.ProblemFactory;
+
+public class ModuleUtil {
+
+	static class ModuleAccumulatorEnvironment extends NameEnvironment {
+		public ModuleAccumulatorEnvironment(IJavaProject javaProject) {
+			super(javaProject);
+		}
+
+		Set<String> modules = new HashSet<>();
+		public String[] getModules() {
+			String[] mods = new String[this.modules.size()];
+			return this.modules.toArray(mods);
+		}
+		@Override
+		public org.eclipse.jdt.internal.compiler.env.IModule getModule(char[] name) {
+			return null;
+		}
+
+		@Override
+		public void cleanup() {
+			this.modules.clear();
+		}
+
+		@Override
+		public NameEnvironmentAnswer findType(char[][] compoundTypeName, IModuleContext context) {
+			NameEnvironmentAnswer answer = super.findType(compoundTypeName, context);
+			if (answer.moduleName() != null) {
+				this.modules.add(new String(answer.moduleName()));
+			}
+			return answer;
+		}
+
+		@Override
+		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext context) {
+			NameEnvironmentAnswer answer = super.findType(typeName, packageName, context);
+			if (answer != null && answer.moduleName() != null) {
+				this.modules.add(new String(answer.moduleName()));
+			}
+			return answer;
+		}
+
+		@Override
+		public boolean isPackage(char[][] parentPackageName, char[] packageName, IModuleContext context) {
+			return super.isPackage(parentPackageName, packageName, context);
+		}
+	}
+	private static Compiler newCompiler(ModuleAccumulatorEnvironment environment, IJavaProject javaProject) {
+		Map<String, String> projectOptions = javaProject.getOptions(true);
+		CompilerOptions compilerOptions = new CompilerOptions(projectOptions);
+		compilerOptions.performMethodsFullRecovery = true;
+		compilerOptions.performStatementsRecovery = true;
+		ICompilerRequestor requestor = new ICompilerRequestor() {
+			@Override
+			public void acceptResult(CompilationResult result) {
+				// Nothing to do here
+			}
+		};
+		Compiler newCompiler = new Compiler(
+			environment,
+			DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+			compilerOptions,
+			requestor,
+			ProblemFactory.getProblemFactory(Locale.getDefault()));
+
+		return newCompiler;
+	}
+	public static String[] getReferencedModules(IJavaProject project) throws CoreException {
+
+		ModuleAccumulatorEnvironment environment = new ModuleAccumulatorEnvironment(project);
+		Compiler compiler = newCompiler(environment, project);
+		// First go over the binary roots and see if any of them are modules
+		List<String> required = new ArrayList<>();
+		Set<org.eclipse.jdt.internal.compiler.env.ICompilationUnit> toCompile = new HashSet<>();
+		IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
+		for (IPackageFragmentRoot root : roots) {
+			if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+				IJavaElement[] children = root.getChildren();
+				for (IJavaElement child : children) {
+					if (child instanceof IPackageFragment) {
+						IPackageFragment fragment = (IPackageFragment) child;
+						if (fragment.isDefaultPackage()) continue;
+						ICompilationUnit[] units = fragment.getCompilationUnits();
+						if (units.length != 0) {
+							String pack = fragment.getElementName();
+							for (ICompilationUnit iUnit : units) {
+								org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceFile = 
+										new BasicCompilationUnit(iUnit.getSource().toCharArray(), CharOperation.splitOn('.', pack.toCharArray()), iUnit.getPath().toOSString());
+								toCompile.add(sourceFile);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sources = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[toCompile.size()];
+		toCompile.toArray(sources);
+		compiler.compile(sources);
+		String[] mods = environment.getModules();
+		for (String string : mods) {
+			required.add(string);
+		}
+		Collections.sort(required, new Comparator<String>() {
+			@Override
+			public int compare(String o1, String o2) {
+				return o1.compareTo(o2);
+			}
+		});
+		return required.toArray(new String[required.size()]);
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
index 98385b8..fd7b613 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -24,10 +28,10 @@
 	private char[] contents;
 	private char[] fileName;
 	private char[] mainTypeName;
-
-	public ResourceCompilationUnit(IFile file) {
+	private char[] module;
+	public ResourceCompilationUnit(IFile file, char[] mod) {
 		this.file = file;
-
+		this.module = mod;
 		String f = file.getFullPath().toString();
 		this.fileName = f.toCharArray();
 		int start = f.lastIndexOf("/") + 1; //$NON-NLS-1$
@@ -72,4 +76,9 @@
 	public boolean ignoreOptionalProblems() {
 		return false;
 	}
+
+	@Override
+	public char[] module() {
+		return this.module;
+	}
 }
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 4ad1da7..52aa5f4 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -46,6 +50,7 @@
 import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.ClassSignature;
@@ -751,7 +756,7 @@
 	}
 
 	private static IClassFile getClassFile(char[] fileName) {
-		int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+		int jarSeparator = CharOperation.lastIndexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
 		int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
 		if (pkgEnd == -1)
 			pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
@@ -845,13 +850,17 @@
 						}
 					}
 					if (path != null) {
-						jar = JavaModelManager.getJavaModelManager().getZipFile(path);
-						for (Enumeration e= jar.entries(); e.hasMoreElements();) {
-							ZipEntry member= (ZipEntry) e.nextElement();
-							String entryName= member.getName();
-							if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
-								reader = ClassFileReader.read(jar, entryName);
-								break;
+						if (JavaModelManager.isJrt(path)) {
+							return ClassFileConstants.JDK9;
+						} else {
+							jar = JavaModelManager.getJavaModelManager().getZipFile(path);
+							for (Enumeration e= jar.entries(); e.hasMoreElements();) {
+								ZipEntry member= (ZipEntry) e.nextElement();
+								String entryName= member.getName();
+								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
+									reader = ClassFileReader.read(jar, entryName);
+									break;
+								}
 							}
 						}
 					}
@@ -1480,7 +1489,7 @@
 		if (referenceBinding.isLocalType() || referenceBinding.isAnonymousType()) {
 			// local or anonymous type
 			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fileName)) {
-				int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+				int jarSeparator = CharOperation.lastIndexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
 				int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
 				if (pkgEnd == -1)
 					pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
diff --git a/org.eclipse.jdt.core/plugin.xml b/org.eclipse.jdt.core/plugin.xml
index 318c373..d31c26e 100644
--- a/org.eclipse.jdt.core/plugin.xml
+++ b/org.eclipse.jdt.core/plugin.xml
@@ -187,6 +187,17 @@
    </extension>
 
 <!-- =================================================================================== -->
+<!-- Extension: Module Path Container                                                   -->
+<!-- =================================================================================== -->
+<extension
+      point="org.eclipse.jdt.core.classpathContainerInitializer">
+      <classpathContainerInitializer
+            class="org.eclipse.jdt.internal.core.ModulePathContainerInitializer"
+            id="org.eclipse.jdt.MODULE_PATH">
+      </classpathContainerInitializer>
+   </extension>
+
+<!-- =================================================================================== -->
 <!-- Extension: Java File Types                                                          -->
 <!-- =================================================================================== -->
 <extension point="org.eclipse.team.core.fileTypes">
diff --git a/org.eclipse.jdt.core/scripts/ecj.1 b/org.eclipse.jdt.core/scripts/ecj.1
index 1461b12..69f5a9c 100644
--- a/org.eclipse.jdt.core/scripts/ecj.1
+++ b/org.eclipse.jdt.core/scripts/ecj.1
@@ -1,7 +1,13 @@
-.TH ecj 1 "10 August 2015"
+.TH ecj "13 March 2017"
 .LP
 .SH NAME
 ecj \- the eclipse JDT Batch Compiler
+
+.B IMPORTANT :  This is the BETA version for Java 9.
+.B This is an implementation of an early-draft specification developed under the Java
+.B  Community Process (JCP) and is made available for testing and evaluation purposes only.
+.B The code is not compatible with any specification of the JCP.
+
 .SH SYNOPSIS
 .B ecj [OPTION]... [SOURCEFILE]...
 .B ...
@@ -16,6 +22,11 @@
 Here is a summary of all the options, grouped by type.  Explanations are in the \fBOPTIONS\fR section.
 .sp
 .ul
+Module Options
+.sp
+.B -p|--module-path \--module-source-path \--system
+.sp
+.ul
 ClassPath Options
 .sp
 .B \-bootclasspath \-cp|\-classpath \-extdirs \-endorseddirs \-sourcepath \-d \-encoding
@@ -23,7 +34,7 @@
 .ul
 Compliance Options
 .sp
-.B \-target \-1.3 \-1.4 \-1.5 \-1.6 \-1.7 \-1.8 \-source 
+.B \-target \-1.3 \-1.4 \-1.5 \-1.6 \-1.7 \-1.8 \1.9 \-source 
 .sp
 .ul
 Warning Options
@@ -58,6 +69,23 @@
 .SH OPTIONS
 .sp
 .ul
+Module Options (Supported from 9 onwards)
+
+.B
+.IP  "-p|--module-path <dir 1>;<dir 2>;...;<dir P>" 
+This is a list of directories where application modules can be found. Entries are separated by the platform path separator.
+
+.B
+.IP  "--module-source-path <dir 1>;<dir 2>;...;<dir P>" 
+This is a list of directories where source files for modules can be found. Entries are separated by the platform path separator.
+
+
+.B
+.IP  "--system <jdk>"
+ Override location of system modules.
+
+.P
+.ul
 ClassPath Options
 
 .B
@@ -112,7 +140,7 @@
 Compliance Options
 
 .B
-.IP "\-target 1.1 to 1.8 (or 8, 8.0, etc.)"
+.IP "\-target 1.1 to 1.9 (or 9, 9.0, etc.)"
 This specifies the .class file target setting. The possible value are: 
 .br
 .B 1.1
@@ -138,6 +166,9 @@
 .br
 .B 1.8, 8 or 8.0
 (major version: 52 minor: 0)
+.br
+.B 1.9, 9 or 9.0
+(major version: 53 minor: 0)
 
 Defaults are: 
 .br
@@ -152,6 +183,8 @@
 1.7 in \-1.7 mode
 .br
 1.8 in \-1.8 mode
+.br
+1.9 in \-1.9 mode
 clcd1.1 can be used to generate the StackMap attribute.
 
 .B
@@ -179,7 +212,11 @@
 Set compliance level to 1.8. Implicit \-source 1.8 \-target 1.8.
 
 .B
-.IP "\-source 1.1 to 1.8 (or 8, 8.0, etc.)"
+.IP \-1.9
+Set compliance level to 1.9. Implicit \-source 1.9\-target 1.9.
+
+.B
+.IP "\-source 1.1 to 1.9 (or 9, 9.0, etc.)"
 This is used to specify the source level expected by the compiler.
 The possible value are: 
 .br
@@ -194,6 +231,8 @@
 .B 1.7, 7 or 7.0
 .br
 .B 1.8, 8 or 8.0
+.br
+.B 1.9, 9 or 9.0
 
 Defaults are: 
 .br
@@ -209,6 +248,8 @@
 .br
 1.8 in \-1.8 mode
 .br
+1.9 in \-1.9 mode
+.br
 In 1.4, assert is treated as a keyword. In 1.5 and 1.6, enum and assert are treated as keywords.
 
 .P
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
index 77f77cd..1717096 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -128,6 +132,12 @@
 	 */
 	int INTERFACE_AND_ANNOTATION= 11;
 
+	/**
+	 * The searched element is a module.
+	 * @since 3.13 BETA_JAVA9
+	 * @category searchFor
+	 */
+	int MODULE= 12;
 	/* Nature of match */
 
 	/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ModuleDeclarationMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ModuleDeclarationMatch.java
new file mode 100644
index 0000000..218fa12
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ModuleDeclarationMatch.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IJavaElement;
+
+/**
+ * A Java search match that represents a module declaration.
+ * The element is an <code>IType</code>.
+ * <p>
+ * This class is intended to be instantiated and subclassed by clients.
+ * </p>
+ *
+ * @since 3.13
+ */
+public class ModuleDeclarationMatch extends SearchMatch {
+
+	/**
+	 * Creates a new type declaration match.
+	 *
+	 * @param element the module declaration
+	 * @param accuracy one of A_ACCURATE or A_INACCURATE
+	 * @param offset the offset the match starts at, or -1 if unknown
+	 * @param length the length of the match, or -1 if unknown
+	 * @param participant the search participant that created the match
+	 * @param resource the resource of the element
+	 */
+	public ModuleDeclarationMatch(IJavaElement element, int accuracy, int offset, int length, SearchParticipant participant, IResource resource) {
+		super(element, accuracy, offset, length, participant, resource);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
index 7975107..ffefdd5 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -1373,6 +1377,10 @@
 	}
 }
 
+private static SearchPattern createModulePattern(String patternString, int limitTo, int matchRule) {
+	return new ModulePattern(patternString.toCharArray(), limitTo, matchRule);
+}
+
 /**
  * Returns a search pattern that combines the given two patterns into an
  * "or" pattern. The search result will match either the left pattern or the
@@ -1640,6 +1648,8 @@
 			return createFieldPattern(stringPattern, limitTo, matchRule);
 		case IJavaSearchConstants.PACKAGE:
 			return createPackagePattern(stringPattern, limitTo, matchRule);
+		case IJavaSearchConstants.MODULE :
+			return createModulePattern(stringPattern, limitTo, matchRule);
 	}
 	return null;
 }
@@ -2113,6 +2123,9 @@
 		case IJavaElement.PACKAGE_FRAGMENT :
 			searchPattern = createPackagePattern(element.getElementName(), maskedLimitTo, matchRule);
 			break;
+		case IJavaElement.JAVA_MODULE :
+			searchPattern = createModulePattern(element.getElementName(), maskedLimitTo, matchRule);
+			break;
 	}
 	if (searchPattern != null)
 		MatchLocator.setFocus(searchPattern, element);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/indexer/HierarchicalASTVisitor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/indexer/HierarchicalASTVisitor.java
index 66f82de..fadfc4b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/indexer/HierarchicalASTVisitor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/indexer/HierarchicalASTVisitor.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -1135,5 +1139,76 @@
 	}
 
 //---- End VariableDeclaration Hierarchy -----------------------------
+//---- Begin Module Hierarchy -----------------------------------------
+	@Override
+	public boolean visit(ModuleDeclaration node) {
+		return visit((ASTNode) node);
+	}
+
+	@Override
+	public void endVisit(ModuleDeclaration node) {
+		endVisit((ASTNode) node);
+	}
+
+	public boolean visit(ModuleStatement node) {
+		return visit((ASTNode) node);
+	}
+
+	public void endVisit(ModuleStatement node) {
+		endVisit((ASTNode) node);
+	}
+
+	@Override
+	public boolean visit(ExportsStatement node) {
+		return visit((ModuleStatement) node);
+	}
+
+	@Override
+	public void endVisit(ExportsStatement node) {
+		endVisit((ModuleStatement) node);
+	}
+
+	@Override
+	public boolean visit(OpensStatement node) {
+		return visit((ModuleStatement) node);
+	}
+
+	@Override
+	public void endVisit(OpensStatement node) {
+		endVisit((ModuleStatement) node);
+	}
+
+	@Override
+	public boolean visit(RequiresStatement node) {
+		return visit((ModuleStatement) node);
+	}
+
+	@Override
+	public void endVisit(RequiresStatement node) {
+		endVisit((ModuleStatement) node);
+	}
+
+	@Override
+	public boolean visit(ProvidesStatement node) {
+		return visit((ModuleStatement) node);
+	}
+
+	@Override
+	public void endVisit(ProvidesStatement node) {
+		endVisit((ModuleStatement) node);
+	}
+
+	@Override
+	public boolean visit(UsesStatement node) {
+		return visit((ModuleStatement) node);
+	}
+
+	@Override
+	public void endVisit(UsesStatement node) {
+		endVisit((ModuleStatement) node);
+	}
+
+//---- End Module Hierarchy -------------------------------------------
+
 //---- End ASTNode Hierarchy -----------------------------------------
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
index f46fd1f..61e2990 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
@@ -25,7 +25,6 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
@@ -38,6 +37,7 @@
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.PackageFragment;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
 import org.eclipse.jdt.internal.core.nd.IReader;
 import org.eclipse.jdt.internal.core.nd.Nd;
 import org.eclipse.jdt.internal.core.nd.db.IndexException;
@@ -64,19 +64,20 @@
 	 */
 	private static BinaryTypeDescriptor createDescriptor(PackageFragment pkg, ClassFile classFile) {
 		String name = classFile.getName();
-		IJavaElement root = pkg.getParent();
+		PackageFragmentRoot root = (PackageFragmentRoot) pkg.getParent();
 		IPath location = JavaIndex.getLocationForElement(root);
-		String entryName = Util.concatWith(pkg.names, classFile.getElementName(), '/');
-		char[] fieldDescriptor = CharArrayUtils.concat(new char[] { 'L' },
-				Util.concatWith(pkg.names, name, '/').toCharArray(), new char[] { ';' });
-		IPath workspacePath = root.getPath();
-		String indexPath;
-
 		if (location == null) {
 			return null;
 		}
+		name = root.getClassFilePath(Util.concatWith(pkg.names, name, '/'));
+		String entryName = Util.concatWith(pkg.names, classFile.getElementName(), '/');
+		char[] fieldDescriptor = CharArrayUtils.concat(new char[] { 'L' },
+				name.toCharArray(), new char[] { ';' });
+		IPath workspacePath = root.getPath();
+		String indexPath;
 
 		if (root instanceof JarPackageFragmentRoot) {
+			entryName = ((JarPackageFragmentRoot) root).getClassFilePath(entryName);
 			// The old version returned this, but it doesn't conform to the spec on IBinaryType.getFileName():
 			indexPath = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
 			// Version that conforms to the JavaDoc spec on IBinaryType.getFileName() -- note that this breaks
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/IndexBinaryType.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/IndexBinaryType.java
index d6216d8..de8ff25 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/IndexBinaryType.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/IndexBinaryType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 Google, Inc and others.
+ * Copyright (c) 2016, 2017 Google, Inc and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -664,4 +664,10 @@
 	public ExternalAnnotationStatus getExternalAnnotationStatus() {
 		return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
 	}
+
+	@Override
+	public char[] getModule() {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
index f5f3311..5e7fd06 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -32,7 +36,11 @@
 		super(documentPath, participant);
 	}
 	public JavaSearchDocument(java.util.zip.ZipEntry zipEntry, IPath zipFilePath, byte[] contents, SearchParticipant participant) {
-		super(zipFilePath + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + zipEntry.getName(), participant);
+		this(zipFilePath + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + zipEntry.getName(), contents, participant);
+	}
+
+	public JavaSearchDocument(String documentPath, byte[] contents, SearchParticipant participant) {
+		super(documentPath, participant);
 		this.byteContents = contents;
 	}
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/NameMatchRequestorWrapper.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/NameMatchRequestorWrapper.java
index 67f8083..c177a93 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/NameMatchRequestorWrapper.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/NameMatchRequestorWrapper.java
@@ -110,6 +110,9 @@
 	}
 	// create handle
 	String classFilePath= resourcePath.substring(separatorIndex + 1);
+	int actualClassIndexSeparator = classFilePath.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR);
+	String moduleName = actualClassIndexSeparator == -1 ? null : classFilePath.substring(0, actualClassIndexSeparator);
+	classFilePath = moduleName != null ? classFilePath.substring(actualClassIndexSeparator + 1, classFilePath.length()) : classFilePath;
 	String[] simpleNames = new Path(classFilePath).segments();
 	String[] pkgName;
 	int length = simpleNames.length-1;
@@ -121,7 +124,7 @@
 	}
 	IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName);
 	if (pkgFragment == null) {
-		pkgFragment= ((PackageFragmentRoot) this.lastPkgFragmentRoot).getPackageFragment(pkgName);
+		pkgFragment= ((PackageFragmentRoot) this.lastPkgFragmentRoot).getPackageFragment(pkgName, moduleName); //BUG 478143
 		// filter org.apache.commons.lang.enum package for projects above 1.5 
 		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=317264
 		if (length == 5 && pkgName[4].equals("enum")) { //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java
index 7f5e331..b8ac9b6 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java
@@ -5,6 +5,14 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for bug 215139
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
index 8111757..b72d039 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -212,6 +216,17 @@
 	public void addMethodReference(char[] methodName, int argCount) {
 		addIndexEntry(METHOD_REF, MethodPattern.createIndexKey(methodName, argCount));
 	}
+	public void addModuleDeclaration(char[] moduleName) {
+		addIndexEntry(MODULE_DECL, ModulePattern.createIndexKey(moduleName));
+	}
+	public void addModuleExportedPackages(char[] packageName) {
+		char[][] tokens = CharOperation.splitOn('.', packageName);
+		for (int i = 0, l = tokens.length; i < l; ++i)
+			addNameReference(tokens[i]);
+	}
+	public void addModuleReference(char[] moduleName) {
+		addIndexEntry(MODULE_REF, ModulePattern.createIndexKey(moduleName));
+	}
 	public void addNameReference(char[] name) {
 		addIndexEntry(REF, name);
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
index 7dc6347..427760f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -23,15 +27,10 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.core.search.SearchParticipant;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
-import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.Index;
@@ -40,11 +39,10 @@
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
 @SuppressWarnings("rawtypes")
-class AddJarFileToIndex extends IndexRequest {
+class AddJarFileToIndex extends BinaryContainer {
 
 	private static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
 	IFile resource;
-	Scanner scanner;
 	private IndexLocation indexFileURL;
 	private final boolean forceIndexUpdate;
 
@@ -180,7 +178,7 @@
 						// iterate each entry to index it
 						ZipEntry ze = (ZipEntry) e.nextElement();
 						String zipEntryName = ze.getName();
-						if (Util.isClassFileName(zipEntryName) && isValidPackageNameForClass(zipEntryName))
+						if (Util.isClassFileName(zipEntryName) && isValidPackageNameForClassOrisModule(zipEntryName))
 								// the class file may not be there if the package name is not valid
 							indexedFileNames.put(zipEntryName, EXISTS);
 					}
@@ -229,7 +227,7 @@
 					ZipEntry ze = (ZipEntry) e.nextElement();
 					String zipEntryName = ze.getName();
 					if (Util.isClassFileName(zipEntryName) && 
-							isValidPackageNameForClass(zipEntryName)) {
+							isValidPackageNameForClassOrisModule(zipEntryName)) {
 						// index only classes coming from valid packages - https://bugs.eclipse.org/bugs/show_bug.cgi?id=293861
 						final byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
 						JavaSearchDocument entryDocument = new JavaSearchDocument(ze, zipFilePath, classFileBytes, participant);
@@ -276,43 +274,6 @@
 			return super.getJobFamily();
 		return this.containerPath.toOSString(); // external jar
 	}	
-	private boolean isIdentifier() throws InvalidInputException {
-		switch(this.scanner.scanIdentifier()) {
-			// assert and enum will not be recognized as java identifiers 
-			// in 1.7 mode, which are in 1.3.
-			case TerminalTokens.TokenNameIdentifier:
-			case TerminalTokens.TokenNameassert:
-			case TerminalTokens.TokenNameenum:
-				return true;
-			default:
-				return false;
-		}
-	}
-	private  boolean isValidPackageNameForClass(String className) {
-		char[] classNameArray = className.toCharArray();
-		// use 1.7 as the source level as there are more valid identifiers in 1.7 mode
-		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=376673
-		if (this.scanner == null)
-			this.scanner = new Scanner(false /* comment */, true /* whitespace */, false /* nls */,
-					ClassFileConstants.JDK1_7/* sourceLevel */, null/* taskTag */, null/* taskPriorities */, true /* taskCaseSensitive */);
-		
-		this.scanner.setSource(classNameArray); 
-		this.scanner.eofPosition = classNameArray.length - SuffixConstants.SUFFIX_CLASS.length;
-		try {
-			if (isIdentifier()) {
-				while (this.scanner.eofPosition > this.scanner.currentPosition) {
-					if (this.scanner.getNextChar() != '/' || this.scanner.eofPosition <= this.scanner.currentPosition) {
-						return false;
-					}
-					if (!isIdentifier()) return false;
-				}
-				return true;
-			}
-		} catch (InvalidInputException e) {
-			// invalid class name
-		}
-		return false;
-	}
 	protected Integer updatedIndexState() {
 
 		Integer updateState = null;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJrtToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJrtToIndex.java
new file mode 100644
index 0000000..6bf8094
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJrtToIndex.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search.indexing;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileVisitResult;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.index.Index;
+import org.eclipse.jdt.internal.core.index.IndexLocation;
+import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
+
+public class AddJrtToIndex extends BinaryContainer {
+
+	IFile resource;
+	private IndexLocation indexFileURL;
+	private final boolean forceIndexUpdate;
+	static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
+	
+	enum FILE_INDEX_STATE {
+		EXISTS,
+		DELETED
+	}
+
+	public AddJrtToIndex(IFile resource, IndexLocation indexFile, IndexManager manager, final boolean updateIndex) {
+		super(resource.getFullPath(), manager);
+		this.resource = resource;
+		this.indexFileURL = indexFile;
+		this.forceIndexUpdate = updateIndex;
+	}
+	public AddJrtToIndex(IPath jrtPath, IndexLocation indexFile, IndexManager manager, final boolean updateIndex) {
+		// external JAR scenario - no resource
+		super(jrtPath, manager);
+		this.indexFileURL = indexFile;
+		this.forceIndexUpdate = updateIndex;
+	}
+	public boolean equals(Object o) {
+		if (o instanceof AddJrtToIndex) {
+			if (this.resource != null)
+				return this.resource.equals(((AddJrtToIndex) o).resource);
+			if (this.containerPath != null)
+				return this.containerPath.equals(((AddJrtToIndex) o).containerPath);
+		}
+		return false;
+	}
+	public int hashCode() {
+		if (this.resource != null)
+			return this.resource.hashCode();
+		if (this.containerPath != null)
+			return this.containerPath.hashCode();
+		return -1;
+	}
+	
+	private class JrtTraverser implements org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<java.nio.file.Path> {
+		
+		SimpleLookupTable indexedFileNames;
+		public JrtTraverser() {
+		}
+		public JrtTraverser(SimpleLookupTable indexedFileNames) {
+			this.indexedFileNames = indexedFileNames;
+		}
+
+		@Override
+		public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs)
+				throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+
+		@Override
+		public FileVisitResult visitFile(java.nio.file.Path path, java.nio.file.Path mod, BasicFileAttributes attrs)
+				throws IOException {
+			String name = path.getFileName().toString();
+			if (Util.isClassFileName(name) && 
+					isValidPackageNameForClassOrisModule(name)) {
+				this.indexedFileNames.put(name, FILE_INDEX_STATE.EXISTS);
+			}
+			return FileVisitResult.CONTINUE;
+		}
+		@Override
+		public FileVisitResult visitModule(java.nio.file.Path mod) throws IOException {
+			return FileVisitResult.CONTINUE;
+		}
+	}
+	
+	private class JrtIndexer extends JrtTraverser {
+		final SearchParticipant participant;
+		final IPath indexPath;
+		final IndexManager indexManager;
+		final IPath container;
+		final Index index;
+		final File jrt;
+
+		public JrtIndexer(File jrt, SearchParticipant participant, Index index, IPath container, IndexManager indexManager) {
+			this.jrt = jrt;
+			this.participant = (participant != null) ? participant : SearchEngine.getDefaultSearchParticipant();
+			this.index = index;
+			IndexLocation indexLocation = index.getIndexLocation();
+			this.indexPath = indexLocation != null ? new Path(indexLocation.getCanonicalFilePath()) : null;
+			this.container = container;
+			this.indexManager = indexManager;
+		}
+
+		public FileVisitResult visitFile(java.nio.file.Path path, java.nio.file.Path mod, BasicFileAttributes attrs)
+				throws IOException {
+			String name = path.getFileName().toString();
+			if (Util.isClassFileName(name) && 
+					isValidPackageNameForClassOrisModule(name)) {
+				try {
+					String fullPath = path.toString();
+					byte[] classFileBytes;
+					classFileBytes = JRTUtil.getClassfileContent(this.jrt, fullPath, mod.toString());
+					String docFullPath =  this.container.toString() + JAR_SEPARATOR + mod.toString() + JAR_SEPARATOR + fullPath;
+					JavaSearchDocument entryDocument = new JavaSearchDocument(docFullPath, classFileBytes, this.participant);
+					this.indexManager.indexDocument(entryDocument, this.participant, this.index, this.indexPath);
+				} catch (IOException | ClassFormatException e) {
+					e.printStackTrace();
+				}
+			}
+			return FileVisitResult.CONTINUE;
+		}
+	}
+
+	public boolean execute(IProgressMonitor progressMonitor) {
+
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
+
+		if (hasPreBuiltIndex()) {
+			boolean added = this.manager.addIndex(this.containerPath, this.indexFileURL);
+			if (added) return true;	
+			this.indexFileURL = null;
+		}
+
+		try {
+			// if index is already cached, then do not perform any check
+			// MUST reset the IndexManager if a jar file is changed
+			if (this.manager.getIndexForUpdate(this.containerPath, false, /*do not reuse index file*/ false /*do not create if none*/) != null) {
+				if (JobManager.VERBOSE)
+					org.eclipse.jdt.internal.core.util.Util.verbose("-> no indexing required (index already exists) for " + this.containerPath); //$NON-NLS-1$
+				return true;
+			}
+
+			final Index index = this.manager.getIndexForUpdate(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
+			if (index == null) {
+				if (JobManager.VERBOSE)
+					org.eclipse.jdt.internal.core.util.Util.verbose("-> index could not be created for " + this.containerPath); //$NON-NLS-1$
+				return true;
+			}
+			index.separator = JAR_SEPARATOR;
+			ReadWriteMonitor monitor = index.monitor;
+			if (monitor == null) {
+				if (JobManager.VERBOSE)
+					org.eclipse.jdt.internal.core.util.Util.verbose("-> index for " + this.containerPath + " just got deleted"); //$NON-NLS-1$//$NON-NLS-2$
+				return true; // index got deleted since acquired
+			}
+			try {
+				final String fileName;
+				final IPath container;
+				monitor.enterWrite(); // ask permission to write
+
+				if (this.resource != null) {
+					URI location = this.resource.getLocationURI();
+					if (location == null) return false;
+					if (JavaModelManager.JRT_ACCESS_VERBOSE)
+						System.out.println("(" + Thread.currentThread() + ") [AddJrtFileToIndex.execute()] Creating ZipFile on " + location.getPath()); //$NON-NLS-1$	//$NON-NLS-2$
+					File file = null;
+					try {
+						file = org.eclipse.jdt.internal.core.util.Util.toLocalFile(location, progressMonitor);
+					} catch (CoreException e) {
+						if (JobManager.VERBOSE) {
+							org.eclipse.jdt.internal.core.util.Util.verbose("-> failed to index " + location.getPath() + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+							e.printStackTrace();
+						}
+					}
+					if (file == null) {
+						if (JobManager.VERBOSE)
+							org.eclipse.jdt.internal.core.util.Util.verbose("-> failed to index " + location.getPath() + " because the file could not be fetched"); //$NON-NLS-1$ //$NON-NLS-2$
+						return false;
+					}
+					fileName = file.getAbsolutePath();
+					container =  this.resource.getFullPath().makeRelative();
+					// absolute path relative to the workspace
+				} else {
+					
+					fileName = this.containerPath.toOSString();
+					container = this.containerPath;
+				}
+
+
+				if (JobManager.VERBOSE)
+					org.eclipse.jdt.internal.core.util.Util.verbose("-> indexing " + fileName); //$NON-NLS-1$
+				long initialTime = System.currentTimeMillis();
+				String[] paths = index.queryDocumentNames(""); // all file names //$NON-NLS-1$
+				if (paths != null) {
+					int max = paths.length;
+					/* check integrity of the existing index file
+					 * if the length is equal to 0, we want to index the whole jrt again
+					 * If not, then we want to check that there is no missing entry, if
+					 * one entry is missing then we recreate the index
+					 */
+					
+					final SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
+					for (int i = 0; i < max; i++)
+						indexedFileNames.put(paths[i], FILE_INDEX_STATE.DELETED);
+					
+					org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(new File(fileName), 
+							new JrtTraverser(indexedFileNames), JRTUtil.NOTIFY_FILES);
+
+					boolean needToReindex = indexedFileNames.elementSize != max; // a new file was added
+					if (!needToReindex) {
+						Object[] valueTable = indexedFileNames.valueTable;
+						for (int i = 0, l = valueTable.length; i < l; i++) {
+							if (valueTable[i] == FILE_INDEX_STATE.DELETED) {
+								needToReindex = true; // a file was deleted so re-index
+								break;
+							}
+						}
+						if (!needToReindex) {
+							if (JobManager.VERBOSE)
+								org.eclipse.jdt.internal.core.util.Util.verbose("-> no indexing required (index is consistent with library) for " //$NON-NLS-1$
+								+ fileName + " (" //$NON-NLS-1$
+								+ (System.currentTimeMillis() - initialTime) + "ms)"); //$NON-NLS-1$
+							this.manager.saveIndex(index); // to ensure its placed into the saved state
+							return true;
+						}
+					}
+				}
+
+				// Index the jrt for the first time or reindex the jrt in case the previous index file has been corrupted
+				// index already existed: recreate it so that we forget about previous entries
+				if (!this.manager.resetIndex(this.containerPath)) {
+					// failed to recreate index, see 73330
+					this.manager.removeIndex(this.containerPath);
+					return false;
+				}
+				
+				File jrt = new File(fileName);
+				org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(jrt, 
+						new JrtIndexer(jrt, SearchEngine.getDefaultSearchParticipant(), index, container, this.manager), JRTUtil.NOTIFY_FILES);
+
+				if(this.forceIndexUpdate) {
+					this.manager.savePreBuiltIndex(index);
+				}
+				else {
+					this.manager.saveIndex(index);
+				}
+				if (JobManager.VERBOSE)
+					org.eclipse.jdt.internal.core.util.Util.verbose("-> done indexing of " //$NON-NLS-1$
+						+ fileName + " (" //$NON-NLS-1$
+						+ (System.currentTimeMillis() - initialTime) + "ms)"); //$NON-NLS-1$
+			} finally {
+				monitor.exitWrite();
+			}
+		} catch (IOException e ) {
+			if (JobManager.VERBOSE) {
+				org.eclipse.jdt.internal.core.util.Util.verbose("-> failed to index " + this.containerPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+				e.printStackTrace();
+			}
+			this.manager.removeIndex(this.containerPath);
+			return false;
+		}
+		return true;
+	}
+	public String getJobFamily() {
+		if (this.resource != null)
+			return super.getJobFamily();
+		return this.containerPath.toOSString(); // external jar
+	}	
+	protected Integer updatedIndexState() {
+
+		Integer updateState = null;
+		if(hasPreBuiltIndex()) {
+			updateState = IndexManager.REUSE_STATE;
+		}
+		else {
+			updateState = IndexManager.REBUILDING_STATE;
+		}
+		return updateState;
+	}
+	public String toString() {
+		return "indexing " + this.containerPath.toString(); //$NON-NLS-1$
+	}
+
+	protected boolean hasPreBuiltIndex() {
+		return !this.forceIndexUpdate && (this.indexFileURL != null && this.indexFileURL.exists());
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryContainer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryContainer.java
new file mode 100644
index 0000000..2d13812
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryContainer.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search.indexing;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+
+public abstract class BinaryContainer extends IndexRequest {
+
+	Scanner scanner;
+	public BinaryContainer(IPath containerPath, IndexManager manager) {
+		super(containerPath, manager);
+	}
+
+	private boolean isIdentifier() throws InvalidInputException {
+		switch(this.scanner.scanIdentifier()) {
+			// assert and enum will not be recognized as java identifiers 
+			// in 1.7 mode, which are in 1.3.
+			case TerminalTokens.TokenNameIdentifier:
+			case TerminalTokens.TokenNameassert:
+			case TerminalTokens.TokenNameenum:
+				return true;
+			default:
+				return false;
+		}
+	}
+	protected boolean isValidPackageNameForClassOrisModule(String className) {
+		if (className.substring(0, className.length() - (SuffixConstants.SUFFIX_CLASS.length)).equals(new String(IIndexConstants.MODULE_INFO))) 
+			return true;
+		char[] classNameArray = className.toCharArray();
+		// use 1.7 as the source level as there are more valid identifiers in 1.7 mode
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=376673
+		if (this.scanner == null)
+			this.scanner = new Scanner(false /* comment */, true /* whitespace */, false /* nls */,
+					ClassFileConstants.JDK1_7/* sourceLevel */, null/* taskTag */, null/* taskPriorities */, true /* taskCaseSensitive */);
+		
+		this.scanner.setSource(classNameArray); 
+		this.scanner.eofPosition = classNameArray.length - SuffixConstants.SUFFIX_CLASS.length;
+		try {
+			if (isIdentifier()) {
+				while (this.scanner.eofPosition > this.scanner.currentPosition) {
+					if (this.scanner.getNextChar() != '/' || this.scanner.eofPosition <= this.scanner.currentPosition) {
+						return false;
+					}
+					if (!isIdentifier()) return false;
+				}
+				return true;
+			}
+		} catch (InvalidInputException e) {
+			// invalid class name
+		}
+		return false;
+	}
+}
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 8486bc9..27c2223 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -25,6 +29,10 @@
 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.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
+import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.compiler.env.IModule.IService;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -145,6 +153,13 @@
 			}
 			addFieldReference(TypeConstants.TYPE);
 		}
+		if ((bits & TagBits.AnnotationForModule) != 0) {
+			if (compoundName == null) {
+				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
+				addTypeReference(compoundName[compoundName.length-1]);
+			}
+			addFieldReference(TypeConstants.UPPER_MODULE);
+		}
 	}
 	private void addBinaryRetentionAnnotation(long bits) {
 		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY;
@@ -632,6 +647,12 @@
 			if (contents == null) return;
 			final String path = this.document.getPath();
 			ClassFileReader reader = new ClassFileReader(contents, path == null ? null : path.toCharArray());
+			
+			IModule module = reader.getModuleDeclaration();
+			if (module != null) {
+				indexModule(module);
+				return;
+			}
 
 			// first add type references
 			char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
@@ -825,6 +846,53 @@
 		}
 	}
 	
+	private void indexModule(IModule module) {
+		addModuleDeclaration(module.name());
+		IModuleReference[] requiredModules = module.requires();
+		if (requiredModules != null) {
+			for (IModuleReference req : requiredModules) {
+				addModuleReference(req.name());
+			}
+		}
+		indexPackageExport(module.exports());
+		indexPackageExport(module.opens());
+		char[][] refUsed = module.uses();
+		if (refUsed != null) {
+			for (char[] ref : refUsed) {
+				indexTypeReference(ref);
+			}
+		}
+		IService[] services = module.provides();
+		if (services != null) {
+			for (IService service : services) {
+				indexTypeReference(service.name());
+				indexTypeReferences(service.with());
+			}
+		}
+	}
+	private void indexPackageExport(IPackageExport[] exportedPackages) {
+		if (exportedPackages != null) {
+			for (IPackageExport pack : exportedPackages) {
+				addModuleExportedPackages(pack.name());
+				char[][] tgtTokens = pack.targets();
+				char[] tgt = tgtTokens != null ? CharOperation.concatWith(tgtTokens, '.') : CharOperation.NO_CHAR;
+				if (!tgt.equals(CharOperation.NO_CHAR)) addModuleExportedPackages(tgt);
+			}
+		}
+	}
+	private void indexTypeReferences(char[][] ref) {
+		if (ref == null || ref.equals(CharOperation.NO_CHAR))
+			return;
+		for (int i = 0; i < ref.length; i++) {
+			addTypeReference(ref[i]);
+		}
+	}
+	private void indexTypeReference(char[] ref) {
+		if (ref == null || ref.equals(CharOperation.NO_CHAR))
+			return;
+		addTypeReference(ref);
+	}
+	
 	private char[] removeFirstSyntheticParameter(char[] descriptor) {
 		if (descriptor == null) return null;
 		if (descriptor.length < 3) return descriptor;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
index 1234a05..3341006 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -25,7 +29,10 @@
 	char[] METHOD_DECL_PLUS= "methodDeclPlus".toCharArray(); //$NON-NLS-1$
 	char[] CONSTRUCTOR_DECL= "constructorDecl".toCharArray(); //$NON-NLS-1$
 	char[] FIELD_DECL= "fieldDecl".toCharArray(); //$NON-NLS-1$
+	char[] MODULE_DECL= "moduleDecl".toCharArray(); //$NON-NLS-1$
+	char[] MODULE_REF= "moduleRef".toCharArray(); //$NON-NLS-1$
 	char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
+	char[] MODULE_INFO = "module-info".toCharArray(); ////$NON-NLS-1$
 	char[][] COUNTS=
 		new char[][] { new char[] {'/', '0'}, new char[] {'/', '1'}, new char[] {'/', '2'}, new char[] {'/', '3'}, new char[] {'/', '4'},
 			new char[] {'/', '5'}, new char[] {'/', '6'}, new char[] {'/', '7'}, new char[] {'/', '8'}, new char[] {'/', '9'}
@@ -64,4 +71,5 @@
 	int TYPE_PARAM_PATTERN = 0x0400;
 	int AND_PATTERN = 0x0800;
 	int ANNOT_REF_PATTERN = 0x1000;
+	int MODULE_PATTERN = 0x2000;
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index b0b6186..b3486a5 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -42,6 +46,7 @@
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
 import org.eclipse.jdt.internal.core.ClasspathEntry;
@@ -592,6 +597,14 @@
 	this.indexLibrary(path, requestingProject, indexURL, false);
 }
 
+private IndexRequest getRequest(Object target, IPath jPath, IndexLocation indexFile, IndexManager manager, boolean updateIndex) {
+	return isJrt(((File) target).getName()) ? new AddJrtToIndex(jPath, indexFile, this, updateIndex) :
+		new AddJarFileToIndex(jPath, indexFile, this, updateIndex);
+}
+
+private boolean isJrt(String fileName) {
+	return fileName != null && fileName.endsWith(JRTUtil.JRT_FS_JAR);
+}
 /**
  * Trigger addition of a library to an index
  * Note: the actual operation is performed in background
@@ -619,9 +632,11 @@
 	IndexRequest request = null;
 	Object target = JavaModel.getTarget(path, true);
 	if (target instanceof IFile) {
-		request = new AddJarFileToIndex((IFile) target, indexFile, this, forceIndexUpdate);
+		request = isJrt(((IFile) target).getFullPath().toOSString()) ? 
+				new AddJrtToIndex((IFile) target, indexFile, this, forceIndexUpdate) :
+					new AddJarFileToIndex((IFile) target, indexFile, this, forceIndexUpdate);
 	} else if (target instanceof File) {
-		request = new AddJarFileToIndex(path, indexFile, this, forceIndexUpdate);
+		request = getRequest(target, path, indexFile, this, forceIndexUpdate);
 	} else if (target instanceof IContainer) {
 		request = new IndexBinaryFolder((IContainer) target, this);
 	} else {
@@ -727,9 +742,11 @@
 	} else if (target instanceof IFolder) {
 		request = new IndexBinaryFolder((IFolder) target, this);
 	} else if (target instanceof IFile) {
-		request = new AddJarFileToIndex((IFile) target, null, this, updateIndex);
+		request = isJrt(((IFile) target).getFullPath().toOSString()) ? 
+				new AddJrtToIndex((IFile) target, null, this, updateIndex) :
+					new AddJarFileToIndex((IFile) target, null, this, updateIndex);
 	} else if (target instanceof File) {
-		request = new AddJarFileToIndex(containerPath, null, this, updateIndex);
+		request = getRequest(target, containerPath, null, this, updateIndex);
 	}
 	if (request != null)
 		request(request);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
index 4972e13..2448f92 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
@@ -5,6 +5,10 @@
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -299,6 +303,24 @@
 	addDefaultConstructorIfNecessary(typeInfo);
 	pushTypeName(typeInfo.name);
 }
+public void enterModule(ModuleInfo moduleInfo) {
+	this.indexer.addModuleDeclaration(moduleInfo.moduleName);
+	if (moduleInfo.requires != null) {
+		for (ISourceElementRequestor.RequiresInfo req : moduleInfo.requires) {
+			if (req == null || req.moduleName == null || req.moduleName.equals(CharOperation.NO_CHAR)) continue;
+			this.indexer.addModuleReference(req.moduleName);
+		}
+	}
+	if (moduleInfo.exports != null) {
+		for (ISourceElementRequestor.PackageExportInfo packInfo : moduleInfo.exports) {
+			if (packInfo == null || packInfo.pkgName == null || packInfo.pkgName.equals(CharOperation.NO_CHAR)) continue;
+			this.indexer.addModuleExportedPackages(packInfo.pkgName);
+			char[][] tgt = packInfo.targets;
+			if (tgt != null && !tgt.equals(CharOperation.NO_CHAR_CHAR)) 
+				this.indexer.addModuleReference(CharOperation.concatWith(tgt, '.'));
+		}
+	}
+}
 /**
  * @see ISourceElementRequestor#enterMethod(ISourceElementRequestor.MethodInfo)
  */
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
index d87228d..c70848f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
@@ -31,7 +31,8 @@
 	TagBits.AnnotationForLocalVariable |
 	TagBits.AnnotationForField |
 	TagBits.AnnotationForConstructor |
-	TagBits.AnnotationForAnnotationType;
+	TagBits.AnnotationForAnnotationType |
+	TagBits.AnnotationForModule;
 private static final char[] JAVA_LANG_ANNOTATION_ELEMENTTYPE = CharOperation.concatWith(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, '.');
 public static char[] convertClassFileFormat(char[] name) {
 	return CharOperation.replaceOnCopy(name, '/', '.');
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
index 452b0f6..ffb7b83 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -23,6 +27,11 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.compiler.env.IPackageLookup;
+import org.eclipse.jdt.internal.compiler.env.ITypeLookup;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
@@ -30,7 +39,7 @@
 import org.eclipse.jdt.internal.core.util.Util;
 
 @SuppressWarnings("rawtypes")
-public class ClasspathSourceDirectory extends ClasspathLocation {
+public class ClasspathSourceDirectory extends ClasspathLocation implements IModulePathEntry {
 
 	IContainer sourceFolder;
 	SimpleLookupTable directoryCache;
@@ -106,12 +115,16 @@
 	return this.sourceFolder.equals(((ClasspathSourceDirectory) o).sourceFolder);
 }
 
+public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+	return findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
+}
 public NameEnvironmentAnswer findClass(String sourceFileWithoutExtension, String qualifiedPackageName, String qualifiedSourceFileWithoutExtension) {
 	SimpleLookupTable dirTable = directoryTable(qualifiedPackageName);
 	if (dirTable != null && dirTable.elementSize > 0) {
 		IFile file = (IFile) dirTable.get(sourceFileWithoutExtension);
 		if (file != null) {
-			return new NameEnvironmentAnswer(new ResourceCompilationUnit(file), null /* no access restriction */);
+			return new NameEnvironmentAnswer(new ResourceCompilationUnit(file, 
+					this.module == null ? null : this.module.name()), null /* no access restriction */);
 		}
 	}
 	return null;
@@ -141,4 +154,25 @@
 	return this.sourceFolder.getFullPath().toString();
 }
 
+@Override
+public ITypeLookup typeLookup() {
+	//
+	return this::findClass;
+}
+
+@Override
+public IPackageLookup packageLookup() {
+	//
+	return this::isPackage;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironment() {
+	return this;
+}
+
+@Override
+public IModuleEnvironment getLookupEnvironmentFor(IModule mod) {
+	return this.module == mod ? this : null;
+}
 }
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 ec9f02e..e9ad82e 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -12,38 +16,56 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IPackageDeclaration;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModuleContext;
+import org.eclipse.jdt.internal.compiler.env.IModuleEnvironment;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.ClasspathEntry;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaElementRequestor;
 import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.ModuleDescriptionInfo;
+import org.eclipse.jdt.internal.core.NameLookup;
 import org.eclipse.jdt.internal.core.PackageFragmentRoot;
 import org.eclipse.jdt.internal.core.builder.ClasspathJar;
+import org.eclipse.jdt.internal.core.builder.ClasspathJrt;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
 import org.eclipse.jdt.internal.core.util.Util;
 
 /*
  * A name environment based on the classpath of a Java project.
  */
-public class JavaSearchNameEnvironment implements INameEnvironment, SuffixConstants {
+public class JavaSearchNameEnvironment implements IModuleAwareNameEnvironment, SuffixConstants {
 
-	LinkedHashSet<ClasspathLocation> locationSet;
+	LinkedHashSet<IModuleEnvironment> locationSet;
+	Map<String, IModuleDescription> modules;
+	private boolean modulesComputed = false;
+	List<IModulePathEntry> modulePathEntries;
 
 	/*
 	 * A map from the fully qualified slash-separated name of the main type (String) to the working copy
@@ -51,6 +73,8 @@
 	Map<String, org.eclipse.jdt.core.ICompilationUnit> workingCopies;
 
 public JavaSearchNameEnvironment(IJavaProject javaProject, org.eclipse.jdt.core.ICompilationUnit[] copies) {
+	this.modulePathEntries = new ArrayList<>();
+	this.modules = new HashMap<>();
 	this.locationSet = computeClasspathLocations((JavaProject) javaProject);
 	this.workingCopies = getWorkingCopyMap(copies);
 }
@@ -69,6 +93,7 @@
 				String mainTypeName = Util.getNameWithoutJavaLikeExtension(cuName);
 				String qualifiedMainTypeName = pkg.length() == 0 ? mainTypeName : pkg.replace('.', '/') + '/' + mainTypeName;
 				result.put(qualifiedMainTypeName, workingCopy);
+				// TODO : JAVA 9 - module-info.java has the same name across modules - Any issues here?
 			}
 		}
 	} catch (JavaModelException e) {
@@ -82,11 +107,11 @@
 }
 
 void addProjectClassPath(JavaProject javaProject) {
-	LinkedHashSet<ClasspathLocation> locations = computeClasspathLocations(javaProject);
+	LinkedHashSet<IModuleEnvironment> locations = computeClasspathLocations(javaProject);
 	if (locations != null) this.locationSet.addAll(locations);
 }
 
-private LinkedHashSet<ClasspathLocation> computeClasspathLocations(JavaProject javaProject) {
+private LinkedHashSet<IModuleEnvironment> computeClasspathLocations(JavaProject javaProject) {
 
 	IPackageFragmentRoot[] roots = null;
 	try {
@@ -94,7 +119,7 @@
 	} catch (JavaModelException e) {
 		return null;// project doesn't exist
 	}
-	LinkedHashSet<ClasspathLocation> locations = new LinkedHashSet<ClasspathLocation>();
+	LinkedHashSet<IModuleEnvironment> locations = new LinkedHashSet<>();
 	int length = roots.length;
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
 	for (int i = 0; i < length; i++) {
@@ -104,25 +129,58 @@
 	return locations;
 }
 
-private ClasspathLocation mapToClassPathLocation( JavaModelManager manager, PackageFragmentRoot root) {
+private void computeModules() {
+	if (!this.modulesComputed) {
+		this.modulesComputed = true;
+		JavaElementRequestor requestor = new JavaElementRequestor();
+		try {
+			JavaModelManager.getModulePathManager().seekModule(CharOperation.ALL_PREFIX, true, requestor);
+			IModuleDescription[] mods = requestor.getModules();
+			for (IModuleDescription mod : mods) {
+				this.modules.putIfAbsent(mod.getElementName(), mod);
+			}
+		} catch (JavaModelException e) {
+			// do nothing
+		}
+	}
+}
+private ClasspathLocation mapToClassPathLocation(JavaModelManager manager, PackageFragmentRoot root) {
 	ClasspathLocation cp = null;
 	IPath path = root.getPath();
+	IModuleDescription imd = root.getModuleDescription();
+	IModule mod = NameLookup.getModuleDescriptionInfo(imd);
+	this.modules.put(new String(mod.name()), imd);
+	IModulePathEntry ime = null;
 	try {
 		if (root.isArchive()) {
 			ClasspathEntry rawClasspathEntry = (ClasspathEntry) root.getRawClasspathEntry();
-			cp = new ClasspathJar(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(), ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true));
+			cp = JavaModelManager.isJrt(path) ? 
+					new ClasspathJrt(path.toOSString(), 
+							ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true), this) :
+						new ClasspathJar(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(),
+								ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry,
+										((IJavaProject) root.getParent()).getProject(), true),
+								this, rawClasspathEntry.isAutomaticModule());		
+			ime = (IModulePathEntry) cp;
 		} else {
 			Object target = JavaModel.getTarget(path, true);
 			if (target != null) {
 				if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
 					cp = new ClasspathSourceDirectory((IContainer)target, root.fullExclusionPatternChars(), root.fullInclusionPatternChars());
+					ime = (IModulePathEntry) cp;
 				} else {
 					ClasspathEntry rawClasspathEntry = (ClasspathEntry) root.getRawClasspathEntry();
-					cp = ClasspathLocation.forBinaryFolder((IContainer) target, false, rawClasspathEntry.getAccessRuleSet(),
-														ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true));
+					cp = ClasspathLocation.forBinaryFolder((IContainer) target, false, rawClasspathEntry.getAccessRuleSet(), 
+							ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true), this, rawClasspathEntry.isAutomaticModule());
+					if (cp instanceof IModulePathEntry && ((IModulePathEntry) cp).getModule() != null) {
+						ime = (IModulePathEntry) cp;
+					}
 				}
 			}
 		}
+		cp.setModule(mod);
+		if (ime != null)
+			this.modulePathEntries.add(ime);
 	} catch (CoreException e1) {
 		// problem opening zip file or getting root kind
 		// consider root corrupt and ignore
@@ -130,17 +188,29 @@
 	return cp;
 }
 
-private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, IModuleContext moduleContext) {
+	if (moduleContext == IModuleContext.UNNAMED_MODULE_CONTEXT)
+		return findClass(qualifiedTypeName, typeName);
+
+	IModuleEnvironment[] envs = moduleContext.getEnvironment().toArray(IModuleEnvironment[] :: new);
+	LinkedHashSet<IModuleEnvironment> cLocs = new LinkedHashSet<>();
+	for  (IModuleEnvironment e : envs) {
+		cLocs.add(e);
+	}
+	return findClass(qualifiedTypeName, typeName, cLocs);
+}
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, LinkedHashSet<IModuleEnvironment> locSets) {
 	String
 		binaryFileName = null, qBinaryFileName = null,
 		sourceFileName = null, qSourceFileName = null,
 		qPackageName = null;
 	NameEnvironmentAnswer suggestedAnswer = null;
-	Iterator <ClasspathLocation> iter = this.locationSet.iterator();
+	Iterator <IModuleEnvironment> iter = locSets.iterator();
 	while (iter.hasNext()) {
-		ClasspathLocation location = iter.next();
-		NameEnvironmentAnswer answer;
+		IModuleEnvironment location = iter.next();
+		NameEnvironmentAnswer answer = null;
 		if (location instanceof ClasspathSourceDirectory) {
+			ClasspathSourceDirectory csd = (ClasspathSourceDirectory) location;
 			if (sourceFileName == null) {
 				qSourceFileName = qualifiedTypeName; // doesn't include the file extension
 				sourceFileName = qSourceFileName;
@@ -155,12 +225,12 @@
 			if (workingCopy != null) {
 				answer = new NameEnvironmentAnswer(workingCopy, null /*no access restriction*/);
 			} else {
-				answer = location.findClass(
-					sourceFileName, // doesn't include the file extension
-					qPackageName,
-					qSourceFileName);  // doesn't include the file extension
+					answer = csd.findClass(
+							sourceFileName, // doesn't include the file extension
+							qPackageName,
+							qSourceFileName);  // doesn't include the file extension
 			}
-		} else {
+		} else if (location instanceof ClasspathLocation){
 			if (binaryFileName == null) {
 				qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
 				binaryFileName = qBinaryFileName;
@@ -172,10 +242,12 @@
 				}
 			}
 			answer =
-				location.findClass(
-					binaryFileName,
-					qPackageName,
-					qBinaryFileName);
+					((ClasspathLocation) location).findClass(
+							binaryFileName,
+							qPackageName,
+							qBinaryFileName);
+		} else {
+			// TODO: handle anything other than ClassPathLocation, if any.
 		}
 		if (answer != null) {
 			if (!answer.ignoreIfBetter()) {
@@ -192,20 +264,28 @@
 	return null;
 }
 
-public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
+	return findClass(qualifiedTypeName, typeName, this.locationSet);
+}
+
+@Override
+public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, IModuleContext context) {
 	if (typeName != null)
 		return findClass(
 			new String(CharOperation.concatWith(packageName, typeName, '/')),
-			typeName);
+			typeName, context);
 	return null;
 }
 
+@Override
+public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+	return findType(typeName, 
+			packageName,
+			IModuleContext.UNNAMED_MODULE_CONTEXT);
+}
+
 public NameEnvironmentAnswer findType(char[][] compoundName) {
-	if (compoundName != null)
-		return findClass(
-			new String(CharOperation.concatWith(compoundName, '/')),
-			compoundName[compoundName.length - 1]);
-	return null;
+	return findType(compoundName, IModuleContext.UNNAMED_MODULE_CONTEXT);
 }
 
 public boolean isPackage(char[][] compoundName, char[] packageName) {
@@ -213,11 +293,67 @@
 }
 
 public boolean isPackage(String qualifiedPackageName) {
-	Iterator<ClasspathLocation> iter = this.locationSet.iterator();
+	Iterator<IModuleEnvironment> iter = this.locationSet.iterator();
 	while (iter.hasNext()) {
 		if (iter.next().isPackage(qualifiedPackageName)) return true;
 	}
 	return false;
 }
 
+@Override
+public NameEnvironmentAnswer findType(char[][] compoundName, IModuleContext moduleContext) {
+	if (compoundName != null)
+		return findClass(
+			new String(CharOperation.concatWith(compoundName, '/')),
+			compoundName[compoundName.length - 1],
+			moduleContext);
+	return null;
+}
+
+@Override
+public boolean isPackage(char[][] parentPackageName, char[] packageName, IModuleContext moduleContext) {
+	if (moduleContext == IModuleContext.UNNAMED_MODULE_CONTEXT)
+		return isPackage(parentPackageName, packageName);
+	String qualifiedPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '/'));
+	Stream<IModuleEnvironment> env = moduleContext.getEnvironment();
+	List<IModuleEnvironment> envs = env.collect(Collectors.toList());
+	for (IModuleEnvironment e : envs) {
+		if (e.isPackage(qualifiedPackageName)) 
+			return true;
+	}
+	return false;
+}
+
+@Override
+public IModule getModule(char[] moduleName) {
+	computeModules();
+	IModuleDescription moduleDesc = this.modules.get(new String(moduleName));
+	IModule module = null;
+	try {
+		if (moduleDesc != null)
+			module =  ((ModuleDescriptionInfo)((JavaElement) moduleDesc).getElementInfo());
+	} catch (JavaModelException e) {
+		// do nothing
+	}
+	return module;
+}
+
+@Override
+public IModuleEnvironment getModuleEnvironmentFor(char[] moduleName) {
+	IModule module = null;
+	for (IModulePathEntry mpe : this.modulePathEntries) {
+		if ((module = mpe.getModule(moduleName)) != null)
+			return mpe.getLookupEnvironmentFor(module);
+	}
+	return null;
+}
+
+@Override
+public IModule[] getAllAutomaticModules() {
+	if (this.modulePathEntries == null || this.modulePathEntries.size() == 0)
+		return IModule.NO_MODULES;
+	Set<IModule> set = this.modulePathEntries.stream().map(e -> e.getModule()).filter(m -> m.isAutomatic())
+			.collect(Collectors.toSet());
+	return set.toArray(new IModule[set.size()]);
+}
 }
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 95ce916..1c9893e 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
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Stephan Herrmann - Contribution for
@@ -12,6 +16,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -34,11 +39,13 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeRoot;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.*;
@@ -251,24 +258,27 @@
 		if (!root.isArchive())
 			return Util.newClassFileReader(((JavaElement) type).resource());
 
-		ZipFile zipFile = null;
-		try {
-			IPath zipPath = root.getPath();
-			if (JavaModelManager.ZIP_ACCESS_VERBOSE)
-				System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
-			zipFile = manager.getZipFile(zipPath);
+		String rootPath = root.getPath().toOSString();
+		if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) {
 			String classFileName = classFile.getElementName();
 			String path = Util.concatWith(pkg.names, classFileName, '/');
-			return ClassFileReader.read(zipFile, path);
-		} finally {
-			manager.closeZipFile(zipFile);
+			return ClassFileReader.readFromJrt(new File(rootPath), path, null);
+		} else {
+			ZipFile zipFile = null;
+			try {
+				IPath zipPath = root.getPath();
+				if (JavaModelManager.ZIP_ACCESS_VERBOSE)
+					System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
+				zipFile = manager.getZipFile(zipPath);
+				String classFileName = classFile.getElementName();
+				String path = Util.concatWith(pkg.names, classFileName, '/');
+				return ClassFileReader.read(zipFile, path);
+			} finally {
+				manager.closeZipFile(zipFile);
+			}
 		}
-	} catch (ClassFormatException e) {
+	} catch (ClassFormatException | CoreException | IOException e) {
 		// invalid class file: return null
-	} catch (CoreException e) {
-		// cannot read class file: return null
-	} catch (IOException e) {
-		// cannot read class file: return null
 	}
 	return null;
 }
@@ -922,7 +932,7 @@
 	TypeBinding typeBinding = this.unitScope.getType(compoundName, compoundName.length);
 	this.unitScopeTypeBinding = typeBinding; //cache.
 	if (typeBinding == null || !typeBinding.isValidBinding()) {
-		typeBinding = this.lookupEnvironment.getType(compoundName);
+		typeBinding = this.lookupEnvironment.getType(compoundName, this.unitScope.module());
 	}
 	this.bindings.put(typeKey, typeBinding);
 	return typeBinding != null && typeBinding.isValidBinding() ? typeBinding : null;
@@ -1643,6 +1653,8 @@
 			return new PackageDeclarationMatch(element, accuracy, offset, length, participant, resource);
 		case IJavaElement.TYPE_PARAMETER:
 			return new TypeParameterDeclarationMatch(element, accuracy, offset, length, participant, resource);
+		case IJavaElement.JAVA_MODULE:
+			return new ModuleDeclarationMatch(binding == null ? element : ((JavaElement) element).resolved(binding), accuracy, offset, length, participant, resource);
 		default:
 			return null;
 	}
@@ -2631,10 +2643,16 @@
 				if (this.hierarchyResolver != null) continue;
 
 				ImportReference importRef = (ImportReference) node;
-				Binding binding = (importRef.bits & ASTNode.OnDemand) != 0
+				boolean inModule = (importRef.bits & ASTNode.inModule) != 0;
+				boolean getOnDemand = (importRef.bits & ASTNode.OnDemand) != 0 || inModule;
+				Binding binding = getOnDemand
 					? this.unitScope.getImport(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length), true, importRef.isStatic())
 					: this.unitScope.getImport(importRef.tokens, false, importRef.isStatic());
-				this.patternLocator.matchLevelAndReportImportRef(importRef, binding, this);
+				if (inModule) {
+					nodeSet.addMatch(node, this.patternLocator.resolveLevel(binding)); // report all module-info together
+				} else {
+					this.patternLocator.matchLevelAndReportImportRef(importRef, binding, this);
+				}
 			} else {
 				nodeSet.addMatch(node, this.patternLocator.resolveLevel(node));
 			}
@@ -2701,10 +2719,18 @@
 		for (int i = 0, l = types.length; i < l; i++) {
 			if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
 			TypeDeclaration type = types[i];
-			Integer level = (Integer) nodeSet.matchingNodes.removeKey(type);
-			int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
-			this.inTypeOccurrencesCounts = new HashtableOfIntValues();
-			reportMatching(type, null, accuracy, nodeSet, 1);
+			if (type.isModuleInfo()) {
+				ModuleDeclaration mod = type.scope.compilationUnitScope().referenceContext.moduleDeclaration;
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(mod);
+				int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
+				reportMatching(mod, null, accuracy, nodeSet, 1);
+				return;
+			} else {
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(type);
+				int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
+				this.inTypeOccurrencesCounts = new HashtableOfIntValues();
+				reportMatching(type, null, accuracy, nodeSet, 1);
+			}
 		}
 	}
 
@@ -2842,6 +2868,109 @@
 	}
 }
 /**
+ * Visit the given module declaration and report the nodes that match exactly the
+ * search pattern (i.e. the ones in the matching nodes set)
+ */
+protected void reportMatching(ModuleDeclaration module, IJavaElement parent, int accuracy, MatchingNodeSet nodeSet, int occurrenceCount) throws CoreException {
+	IModuleDescription moduleDesc =  null;
+	Openable openable = this.currentPossibleMatch.openable;
+	if (openable instanceof ITypeRoot) {
+		ITypeRoot typeRoot = (ITypeRoot) openable;
+		try {
+			moduleDesc =  typeRoot.getModule();
+		} catch (JavaModelException e) {
+			// do nothing
+		}
+	}
+	if (moduleDesc == null) // should not happen - safety net.
+		return;
+	if (accuracy > -1) { // report module declaration
+		SearchMatch match = this.patternLocator.newDeclarationMatch(module, moduleDesc, module.moduleBinding, accuracy, module.moduleName.length, this);
+		report(match);
+	}
+	reportMatching(module.requires, module,  nodeSet, moduleDesc);
+	reportMatching(module.exports, nodeSet, moduleDesc);
+	reportMatching(module.opens, nodeSet, moduleDesc);
+	reportMatching(module.services, module, nodeSet, moduleDesc);
+	reportMatching(module.uses, module, nodeSet, moduleDesc);
+}
+
+private void reportMatching(RequiresStatement[] reqs, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) {
+	if (reqs == null || reqs.length == 0)
+		return;
+	try {
+		for (RequiresStatement req : reqs) {
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(req.module);
+			if (level != null) {
+				this.patternLocator.matchReportReference(req.module, moduleDesc, req.resolvedBinding, level.intValue(), this);
+			}
+		}
+	} catch (CoreException e) {
+		// do nothing
+	}
+}
+
+private void reportMatching(PackageVisibilityStatement[] psvs, MatchingNodeSet nodeSet, IModuleDescription moduleDesc)
+		throws JavaModelException, CoreException {
+	if (psvs != null && psvs.length > 0) {
+		for (PackageVisibilityStatement psv : psvs) {
+			ImportReference importRef = psv.pkgRef;
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(importRef);
+			if (level != null) {
+				Binding binding = this.unitScope.getImport(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length), true, false);
+				this.patternLocator.matchReportImportRef(importRef, binding, moduleDesc, level.intValue(), this);
+			}
+			ModuleReference[] tgts = psv.targets;
+			if (tgts == null || tgts.length == 0) return;
+			for (ModuleReference tgt : tgts) {
+				level = (Integer) nodeSet.matchingNodes.removeKey(tgt);
+				if (level != null) {
+					this.patternLocator.matchReportReference(tgt, moduleDesc, tgt.resolve(this.unitScope), level.intValue(), this);
+				}
+			}
+		}
+	}
+}
+private void reportMatching(ProvidesStatement[] provides, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) throws JavaModelException, CoreException {
+	if (provides != null && provides.length > 0) {
+		for (ProvidesStatement service : provides) {
+			TypeReference intf = service.serviceInterface;
+			if (intf != null) {
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(intf);
+				if (level != null)
+					this.patternLocator.matchReportReference(intf, moduleDesc, null, null, module.moduleBinding, level.intValue(), this);
+			}
+			TypeReference[] impls = service.implementations;
+			for (TypeReference impl : impls) {
+				if (impl != null) {
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(impl);
+					if (level != null)
+						this.patternLocator.matchReportReference(impl, moduleDesc, null, null, module.moduleBinding, level.intValue(), this);
+				}
+			}
+		}
+	}
+}
+private void reportMatching(UsesStatement[] uses, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) {
+	if (uses != null && uses.length > 0) {
+		try {
+			for (UsesStatement service : uses) {
+				TypeReference intf = service.serviceInterface;
+				if (intf != null) {
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(intf);
+					if (level != null) {
+						this.patternLocator.matchReportReference(intf, moduleDesc, null, null, module.moduleBinding, level.intValue(), this);
+					}
+				}
+			}
+		} catch (CoreException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+}
+
+/**
  * Visit the given type declaration and report the nodes that match exactly the
  * search pattern (i.e. the ones in the matching nodes set)
  */
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index dd01e3c..b84a57b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * 
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -318,6 +322,10 @@
 	super.consumeExplicitConstructorInvocationWithTypeArguments(flag, recFlag);
 	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
 }
+protected void consumeExportsHeader() {
+	super.consumeExportsHeader();
+	this.patternLocator.match(((ExportsStatement) this.astStack[this.astPtr]).pkgRef, this.nodeSet);
+}
 protected void consumeFieldAccess(boolean isSuperAccess) {
 	super.consumeFieldAccess(isSuperAccess);
 
@@ -483,6 +491,11 @@
 	}
 }
 
+@Override
+protected void consumeModuleHeader() {
+	super.consumeModuleHeader();
+	this.patternLocator.match(((ModuleDeclaration) this.astStack[this.astPtr]), this.nodeSet);
+}
 protected void consumeNormalAnnotation(boolean isTypeAnnotation) {
 	super.consumeNormalAnnotation(isTypeAnnotation);
 	if (this.patternFineGrain == 0 || (this.patternFineGrain & IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE) != 0) {
@@ -504,7 +517,26 @@
 		}
 	}
 }
-
+@Override
+protected void consumeOpensHeader() {
+	super.consumeOpensHeader();
+	this.patternLocator.match(((OpensStatement) this.astStack[this.astPtr]).pkgRef, this.nodeSet);
+}
+@Override
+protected void consumeProvidesInterface() {
+	super.consumeProvidesInterface();
+	ProvidesStatement ref = (ProvidesStatement) this.astStack[this.astPtr];
+	this.patternLocator.match(ref.serviceInterface, this.nodeSet);
+}
+@Override
+protected void consumeProvidesStatement() {
+	super.consumeProvidesStatement();
+	ProvidesStatement ref = (ProvidesStatement) this.astStack[this.astPtr];
+	TypeReference[] impls = ref.implementations;
+	for (TypeReference impl : impls) {
+		this.patternLocator.match(impl, this.nodeSet);
+	}
+}
 protected void consumePrimaryNoNewArrayWithName() {
 	// PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN
 	pushOnExpressionStack(getUnspecifiedReferenceOptimized());
@@ -544,6 +576,24 @@
 		this.patternLocator.match(annotation, this.nodeSet);
 	}
 }
+@Override
+protected void consumeSingleRequiresModuleName() {
+	super.consumeSingleRequiresModuleName();
+	RequiresStatement req = (RequiresStatement) this.astStack[this.astPtr];
+	this.patternLocator.match(req.module, this.nodeSet);
+}
+private void setTarget(boolean flag) {
+	if (this.patternLocator instanceof ModuleLocator) {
+		((ModuleLocator) this.patternLocator).target = flag;
+	}
+}
+@Override
+protected void consumeSingleTargetModuleName() {
+	super.consumeSingleTargetModuleName();
+	setTarget(true);
+	this.patternLocator.match((ModuleReference)this.astStack[this.astPtr], this.nodeSet);
+	setTarget(false);
+}
 
 protected void consumeStatementCatch() {
 	super.consumeStatementCatch();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModuleLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModuleLocator.java
new file mode 100644
index 0000000..d98c722
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModuleLocator.java
@@ -0,0 +1,88 @@
+package org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+public class ModuleLocator extends PatternLocator {
+
+	private ModulePattern pattern;
+	/* package */ boolean target = false;
+
+	public ModuleLocator(ModulePattern pattern) {
+		super(pattern);
+		this.pattern = pattern;
+	}
+	public int match(ModuleDeclaration node, MatchingNodeSet nodeSet) {
+		if (!this.pattern.findDeclarations) return IMPOSSIBLE_MATCH;
+		if (!matchesName(this.pattern.name, node.moduleName)) return IMPOSSIBLE_MATCH;
+		nodeSet.mustResolve = true;
+		return nodeSet.addMatch(node, POSSIBLE_MATCH);
+	}
+	@Override
+	protected int match(ModuleReference node, MatchingNodeSet nodeSet) {
+		if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+		if (!matchesName(this.pattern.name, node.moduleName)) return IMPOSSIBLE_MATCH;
+		if (this.target) {
+			return nodeSet.addMatch(node, ACCURATE_MATCH);
+		}
+		nodeSet.mustResolve = true;
+		return nodeSet.addMatch(node, POSSIBLE_MATCH);
+	}
+	@Override
+	protected int matchContainer() {
+		return COMPILATION_UNIT_CONTAINER;
+	}
+	public int resolveLevel(ASTNode possibleMatchingNode) {
+		if (this.pattern.findDeclarations && possibleMatchingNode instanceof ModuleDeclaration) {
+			return resolveLevel(((ModuleDeclaration) possibleMatchingNode).moduleBinding);
+		}
+		if (this.pattern.findReferences && possibleMatchingNode instanceof ModuleReference) {
+			return resolveLevel(((ModuleReference) possibleMatchingNode).resolve(null));
+		}
+		return IMPOSSIBLE_MATCH;
+	}
+	@Override
+	protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
+		super.matchReportReference(reference, element, elementBinding, accuracy, locator);
+	}
+	@Override
+	protected void matchReportReference(ASTNode reference, IJavaElement element, IJavaElement localElement, IJavaElement[] otherElements, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
+		matchReportReference(reference, element, elementBinding, accuracy, locator);
+	}
+
+	@Override
+	public SearchMatch newDeclarationMatch(ASTNode node, IJavaElement element, Binding elementBinding, int accuracy, int length, MatchLocator locator) {
+		return super.newDeclarationMatch(node, element, elementBinding, accuracy, length, locator);
+	}
+	@Override
+	protected int referenceType() {
+		return IJavaElement.JAVA_MODULE;
+	}
+	public int resolveLevel(Binding binding) {
+		if (binding == null) return INACCURATE_MATCH;
+		if (!(binding instanceof ModuleBinding)) return IMPOSSIBLE_MATCH;
+		return (matchesName(this.pattern.name, binding.readableName())) ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
+			
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModulePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModulePattern.java
new file mode 100644
index 0000000..8e99d10
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ModulePattern.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.search.matching;
+
+import java.io.IOException;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.core.index.EntryResult;
+import org.eclipse.jdt.internal.core.index.Index;
+
+public class ModulePattern extends JavaSearchPattern {
+
+	boolean findDeclarations = true; /* package visible */
+	boolean findReferences = true; /* package visible */
+	char[] name; /* package visible */
+
+	protected static char[][] REF_CATEGORIES = { MODULE_REF };
+	protected static char[][] REF_AND_DECL_CATEGORIES = { MODULE_REF, MODULE_DECL };
+	protected static char[][] DECL_CATEGORIES = { MODULE_DECL };
+
+	public static char[] createIndexKey(char[] name) {
+		return name; // until a need arises, let the name itself be the index key.
+	}
+	protected ModulePattern(int matchRule) {
+		super(MODULE_PATTERN, matchRule);
+	}
+	public ModulePattern(char[] name, int limitTo, int matchRule) {
+		this(matchRule);
+		this.name = name;
+		switch (limitTo & 0xF) {
+			case IJavaSearchConstants.DECLARATIONS :
+				this.findReferences = false;
+				break;
+			case IJavaSearchConstants.REFERENCES :
+				this.findDeclarations = false;
+				break;
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				break;
+		}
+		this.mustResolve = mustResolve();
+	}
+	public void decodeIndexKey(char[] key) {
+		this.name = key;
+	}
+	public SearchPattern getBlankPattern() {
+		return new ModulePattern(R_EXACT_MATCH);
+	}
+	public char[][] getIndexCategories() {
+		if (this.findReferences)
+			return this.findDeclarations ? REF_AND_DECL_CATEGORIES : REF_CATEGORIES;
+		if (this.findDeclarations)
+			return DECL_CATEGORIES;
+		return CharOperation.NO_CHAR_CHAR;
+	}
+	public boolean matchesDecodedKey(SearchPattern decodedPattern) {
+		return matchesName(this.name, ((ModulePattern) decodedPattern).name);
+	}
+	public EntryResult[] queryIn(Index index) throws IOException {
+		char[] key = this.name; // can be null
+		int matchRule = getMatchRule();
+
+		switch(getMatchMode()) {
+			case R_EXACT_MATCH :
+				if (this.name != null) {
+					key = createIndexKey(this.name);
+				} else { // do a prefix query with the selector
+					matchRule &= ~R_EXACT_MATCH;
+					matchRule |= R_PREFIX_MATCH;
+				}
+				break;
+			case R_PREFIX_MATCH :
+				// do a prefix query with the selector
+				break;
+			case R_PATTERN_MATCH :
+				if (this.name != null) {
+					key = createIndexKey(this.name);
+				}
+				// else do a pattern query with just the selector
+				break;
+			case R_REGEXP_MATCH :
+				// TODO implement regular expression match
+				break;
+			case R_CAMELCASE_MATCH:
+			case R_CAMELCASE_SAME_PART_COUNT_MATCH:
+				// do a prefix query with the selector
+				break;
+		}
+
+		return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
+	}
+
+	protected boolean mustResolve() {
+		return true;
+	}
+	protected StringBuffer print(StringBuffer output) {
+		if (this.findDeclarations) {
+			output.append(this.findReferences
+				? "ModuleCombinedPattern: " //$NON-NLS-1$
+				: "ModuleDeclarationPattern: "); //$NON-NLS-1$
+		} else {
+			output.append("ModuleReferencePattern: "); //$NON-NLS-1$
+		}
+		output.append("module "); //$NON-NLS-1$
+		output.append(this.name);
+		return super.print(output);
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
index ff8549d..73bdbcf 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
@@ -179,7 +179,7 @@
 			if (binding instanceof PackageBinding)
 				last = ((PackageBinding) binding).compoundName.length;
 			int start = (int) (positions[0] >>> 32);
-			int end = (int) positions[last - 1];
+			int end = (int) positions[last > 0 ? last - 1 : 0];
 			this.match = locator.newPackageReferenceMatch(element, accuracy, start, end-start+1, importRef);
 			locator.report(this.match);
 		}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
index b667b73..dfb079b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -93,6 +97,8 @@
 			return new LocalVariableLocator((LocalVariablePattern) pattern);
 		case IIndexConstants.TYPE_PARAM_PATTERN:
 			return new TypeParameterLocator((TypeParameterPattern) pattern);
+		case IIndexConstants.MODULE_PATTERN:
+			return new ModuleLocator((ModulePattern) pattern);
 	}
 	return null;
 }
@@ -222,6 +228,12 @@
 	// each subtype should override if needed
 	return IMPOSSIBLE_MATCH;
 }
+protected int match(ModuleDeclaration node, MatchingNodeSet nodeSet) {
+	return IMPOSSIBLE_MATCH;
+}
+protected int match(ModuleReference node, MatchingNodeSet nodeSet) {
+	return IMPOSSIBLE_MATCH;
+}
 public int match(Reference node, MatchingNodeSet nodeSet) {
 	// each subtype should override if needed
 	return IMPOSSIBLE_MATCH;
@@ -418,6 +430,9 @@
 		case IJavaElement.TYPE_PARAMETER:
 			this.match = locator.newTypeParameterReferenceMatch(element, accuracy, offset, reference.sourceEnd-offset+1, reference);
 			break;
+		case IJavaElement.JAVA_MODULE:
+			this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, offset, reference.sourceEnd-offset+1, reference);
+			break;
 	}
 	if (this.match != null) {
 		locator.report(this.match);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
index 99843de..6b5077c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
@@ -1,10 +1,14 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -17,6 +21,7 @@
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -144,7 +149,7 @@
 	return this.sourceFileName;
 }
 boolean hasSimilarMatch() {
-	return this.similarMatch != null && this.source == NO_SOURCE_FILE;
+	return this.similarMatch != null && (this.source == NO_SOURCE_FILE || isModuleInfo(this));
 }
 public int hashCode() {
 	if (this.compoundName == null) return super.hashCode();
@@ -157,13 +162,24 @@
 public boolean ignoreOptionalProblems() {
 	return false;
 }
+private boolean isModuleInfo(PossibleMatch possibleMatch) {
+	return CharOperation.equals(getMainTypeName(), TypeConstants.MODULE_INFO_NAME);
+}
 void setSimilarMatch(PossibleMatch possibleMatch) {
 	// source does not matter on similar match as it is read on
 	// the first stored possible match
-	possibleMatch.source = NO_SOURCE_FILE;
+	possibleMatch.source = isModuleInfo(possibleMatch) ? null : NO_SOURCE_FILE;
 	this.similarMatch = possibleMatch;
 }
 public String toString() {
 	return this.openable == null ? "Fake PossibleMatch" : this.openable.toString(); //$NON-NLS-1$
 }
+@Override
+public char[] module() {
+	if (this.openable instanceof CompilationUnit) {
+		return ((CompilationUnit) this.openable).module();
+	}
+	// TODO BETA_JAVA9 Auto-generated method stub
+	return null;
+}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
index df8ef79..ad5b939 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import java.util.HashSet;
+
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
@@ -45,11 +47,14 @@
 public PossibleMatch[] getPossibleMatches(IPackageFragmentRoot[] roots) {
 	PossibleMatch[] result = new PossibleMatch[this.elementCount];
 	int index = 0;
+	HashSet<IPath> processedHash = new HashSet<>();
 	for (int i = 0, length = roots.length; i < length; i++) {
-		ObjectVector possibleMatches = (ObjectVector) this.rootsToPossibleMatches.get(roots[i].getPath());
-		if (possibleMatches != null) {
+		IPath path = roots[i].getPath();
+		ObjectVector possibleMatches = (ObjectVector) this.rootsToPossibleMatches.get(path);
+		if (possibleMatches != null && !processedHash.contains(path)) {
 			possibleMatches.copyInto(result, index);
 			index += possibleMatches.size();
+			processedHash.add(path);
 		}
 	}
 	if (index < this.elementCount)