Bug 486011 - [1.9][model] Java 9 Support in Java Model

Preliminary code select changes
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 ae76838..d9db009 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
@@ -207,6 +207,8 @@
 
 		// Java model changes related to Java 8
 		JavaElement8Tests.class,
+
+		Java9ElementTests.class,
 	};
 
 	Class[] deprecatedClasses = getDeprecatedJDOMTestClasses();
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/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index c139857..179c57f 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
@@ -964,6 +964,19 @@
 						}
 					}
 				}
+				if (parsedUnit.isModuleInfo()) {
+					ModuleDeclaration module = (ModuleDeclaration) parsedUnit.types[0];//TODO, could be null
+					ExportReference[] exports = module.exports;
+					if (exports != null) {
+						for (ExportReference exportReference : exports) {
+							if (exportReference instanceof SelectionOnExportReference) {
+								char[][] tokens = ((SelectionOnExportReference) exportReference).tokens;
+								this.noProposal = false;
+								this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+							}
+						}
+					}
+				} 
 				if (parsedUnit.types != null || parsedUnit.isPackageInfo()) {
 					if(selectDeclaration(parsedUnit))
 						return;
@@ -1298,6 +1311,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);
 		}
 	}
 	/*
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExportReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExportReference.java
index 36c0005..c258d86 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExportReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExportReference.java
@@ -35,9 +35,9 @@
 
 	public SelectionOnExportReference(char[][] tokens, long[] sourcePositions) {
 		super(tokens, sourcePositions);
-		// TODO Auto-generated constructor stub
 	}
-	public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+
+	public StringBuffer print(int indent, StringBuffer output) {
 
 		printIndent(indent, output).append("<SelectOnExport:"); //$NON-NLS-1$
 		for (int i = 0; i < this.tokens.length; i++) {
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
index d2d3ac8..4944626 100644
--- 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
@@ -16,13 +16,25 @@
 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 StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) {
+
+	public ModuleBinding resolve(Scope scope) {
+		super.resolve(scope);
+		if (this.binding != null) {
+			throw new SelectionNodeFound(this.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('.');
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/model/org/eclipse/jdt/internal/core/NamedMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
index 02639ea..c65a7e5 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
@@ -304,6 +304,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/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index 305cfe6..145c260 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, 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
  *******************************************************************************/
@@ -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,15 @@
 	}
 	return this.elements;
 }
+protected IModuleDescription resolveModule(char[] moduleName) {
+	if (this.openable instanceof CompilationUnit) {
+		// Do what's needed. Question is, how are we going to look up for modules somewhere else in a workspace?
+		// The question is esp. when the usecase is about completing on a module name in a requires clause.
+		Answer answer = this.nameLookup.findModule(new String(moduleName));
+		return answer.module;
+	}
+	return null;
+}
 /**
  * Resolve the type
  */