Fix for Bug 500622 [9][search] Index module-info.java
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 fc73086..7c91891 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, 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
  *******************************************************************************/
@@ -27,7 +31,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.
@@ -52,7 +57,7 @@
 		public PackageExportInfo[] exports;
 	}
 	public static class RequiresInfo {
-		public char[][] moduleName;
+		public char[] moduleName;
 		public int modifiers;
 	}
 	public static class PackageExportInfo {
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 a8e69ab..338270e 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, 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
  *******************************************************************************/
@@ -637,6 +641,7 @@
 			typeInfo.annotations = typeDeclaration.annotations;
 			typeInfo.extraFlags = ExtraFlags.getExtraFlags(typeDeclaration);
 			typeInfo.node = typeDeclaration;
+			fillModuleInfo(typeDeclaration, typeInfo, kind);
 			this.requestor.enterType(typeInfo);
 			switch (kind) {
 				case TypeDeclaration.CLASS_DECL :
@@ -652,28 +657,6 @@
 				case TypeDeclaration.ANNOTATION_TYPE_DECL :
 					implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION;
 					break;
-				case TypeDeclaration.MODULE_DECL:
-					ModuleDeclaration mod = (ModuleDeclaration)typeDeclaration;
-					ModuleInfo modInfo = (ModuleInfo)typeInfo;
-					modInfo.moduleName = mod.moduleName;
-					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 = mod.requires[i].tokens;
-							req.modifiers = mod.requires[i].modifiers;
-						}
-						modInfo.requires = reqs;
-					}
-					if (mod.exportsCount > 0) {
-						ISourceElementRequestor.PackageExportInfo exports[] = new ISourceElementRequestor.PackageExportInfo[mod.exportsCount];
-						for (int i = 0; i < mod.exportsCount; i++) {
-							ISourceElementRequestor.PackageExportInfo exp = new ISourceElementRequestor.PackageExportInfo();
-							exp.pkgName = mod.exports[i].pkgName;
-							modInfo.exports = exports;
-						}					
-					}
-					break;
 			}
 		}
 		if (this.nestedTypeIndex == this.typeNames.length) {
@@ -735,6 +718,31 @@
 		this.nestedTypeIndex--;
 	}
 }
+private void fillModuleInfo(TypeDeclaration typeDeclaration, ISourceElementRequestor.TypeInfo typeInfo, int kind) {
+	if (kind != TypeDeclaration.MODULE_DECL) return;
+	ModuleDeclaration mod = (ModuleDeclaration)typeDeclaration;
+	ModuleInfo modInfo = (ModuleInfo)typeInfo;
+	modInfo.moduleName = mod.moduleName;
+	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].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();
+			exp.pkgName = mod.exports[i].pkgName;
+			exps[i] = exp;
+		}					
+		modInfo.exports = exps;
+	}
+}
 /*
  * 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..07bb273 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();
+	ModuleDeclaration module = (ModuleDeclaration) this.astStack[this.astPtr];
+	TypeReference ref = module.interfaces[module.servicesCount - 1];
+	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,18 @@
 		this.requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 	}
 }
+protected void consumeUsesStatement() {
+	super.consumeUsesStatement();
+	ModuleDeclaration module = (ModuleDeclaration) this.astStack[this.astPtr];
+	TypeReference ref = module.uses[module.usesCount - 1];
+	this.requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+}
+protected void consumeWithClause() {
+	super.consumeWithClause();
+	ModuleDeclaration module = (ModuleDeclaration) this.astStack[this.astPtr];
+	TypeReference ref = module.implementations[module.servicesCount];
+	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/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..9c69eca 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, 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
  *******************************************************************************/
@@ -212,6 +216,17 @@
 	public void addMethodReference(char[] methodName, int argCount) {
 		addIndexEntry(METHOD_REF, MethodPattern.createIndexKey(methodName, argCount));
 	}
+	public void addModuleDeclaration(char[] moduleName) {
+		addIndexEntry(METHOD_DECL, 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, 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
index de2f5d5..6bf8094 100644
--- 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
@@ -25,17 +25,12 @@
 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.classfmt.ClassFormatException;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 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;
@@ -43,10 +38,9 @@
 import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
-public class AddJrtToIndex extends IndexRequest {
+public class AddJrtToIndex extends BinaryContainer {
 
 	IFile resource;
-	Scanner scanner;
 	private IndexLocation indexFileURL;
 	private final boolean forceIndexUpdate;
 	static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
@@ -105,7 +99,7 @@
 				throws IOException {
 			String name = path.getFileName().toString();
 			if (Util.isClassFileName(name) && 
-					isValidPackageNameForClass(name)) {
+					isValidPackageNameForClassOrisModule(name)) {
 				this.indexedFileNames.put(name, FILE_INDEX_STATE.EXISTS);
 			}
 			return FileVisitResult.CONTINUE;
@@ -138,7 +132,7 @@
 				throws IOException {
 			String name = path.getFileName().toString();
 			if (Util.isClassFileName(name) && 
-					isValidPackageNameForClass(name)) {
+					isValidPackageNameForClassOrisModule(name)) {
 				try {
 					String fullPath = path.toString();
 					byte[] classFileBytes;
@@ -299,43 +293,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;
-		}
-	}
-	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/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..a7bea87 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, 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
  *******************************************************************************/
@@ -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;
@@ -632,6 +640,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 +839,43 @@
 		}
 	}
 	
+	private void indexModule(IModule module) {
+		addModuleDeclaration(module.name());
+		IModuleReference[] requiredModules = module.requires();
+		if (requiredModules != null) {
+			for (IModuleReference req : requiredModules) {
+				addModuleReference(req.name());
+			}
+		}
+		IPackageExport[] exportedPackages = module.exports();
+		if (exportedPackages != null) {
+			for (IPackageExport pack : exportedPackages) {
+				addModuleExportedPackages(pack.name());
+				char[][] tgtTokens = pack.exportedTo();
+				char[] tgt = tgtTokens != null ? CharOperation.concatWith(tgtTokens, '.') : CharOperation.NO_CHAR;
+				if (!tgt.equals(CharOperation.NO_CHAR)) addModuleExportedPackages(tgt);
+			}
+		}
+		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());
+				indexTypeReference(service.with());
+			}
+		}
+	}
+	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..27f1ad5 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, 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
  *******************************************************************************/
@@ -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'}
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 8824b1d..e827c9c 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
@@ -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
  *******************************************************************************/
@@ -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.targetModule;
+			if (tgt != null && tgt == CharOperation.NO_CHAR) 
+				this.indexer.addModuleReference(tgt);
+		}
+	}
+}
 /**
  * @see ISourceElementRequestor#enterMethod(ISourceElementRequestor.MethodInfo)
  */
@@ -371,6 +393,9 @@
 		case TypeDeclaration.ENUM_DECL:
 			enterEnum(typeInfo);
 			break;
+		case TypeDeclaration.MODULE_DECL:
+			enterModule((ModuleInfo) typeInfo);
+			break;
 	}
 }