Bug 542896 - [9] unnamed module accessing types via on-demand import of
split package is unreliable

Change-Id: Ib7f1e44edea8e99793806f1d2d37e9b5a80d6212
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 ce83b15..b8e7a88 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2017 Sven Strohschein and others.
+ * Copyright (c) 2016, 2019 Sven Strohschein and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -37,7 +37,7 @@
 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(true);
 
 		PackageBinding packageBinding = new PackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
-		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null);
+		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null, false);
 		assertNotNull(resultBinding);
 
 		assertTrue(nameEnv.isPackageSearchExecuted);
@@ -54,7 +54,7 @@
 
 		LookupEnvironment environment = new LookupEnvironment(null, new CompilerOptions(), null, nameEnv);
 		PackageBinding packageBinding = new PackageBinding(environment);
-		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), environment.module);
+		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), environment.module, false);
 		assertNull(resultBinding); // (not implemented)
 
 		assertTrue(nameEnv.isPackageSearchExecuted);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 5a576b3..6ba004d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2018 IBM Corporation and others.
+ * Copyright (c) 2016, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7467,6 +7467,96 @@
 			deleteProject("ztest");
 		}
 	}
+	public void testBug542896() throws CoreException {
+		IJavaProject java10Project = createJava10Project("bug", new String[] { "src" });
+		try {
+			createFolder("/bug/src/test/platform");
+			createFile("/bug/src/test/platform/Context.java",
+					"package test.platform;\n" + 
+					"\n" + 
+					"import java.net.URI;\n" + 
+					"\n" + 
+					"public interface Context {\n" + 
+					"	public URI getURI();\n" + 
+					"}\n");
+			createFile("/bug/src/test/platform/AbstractContext.java",
+					"package test.platform;\n" + 
+					"\n" + 
+					"import java.net.URI;\n" + 
+					"import java.util.*;\n" + 
+					"import test.*;\n" + 
+					"\n" + 
+					"public abstract class AbstractContext implements Context {\n" + 
+					"	Iterable<URI> uris = new ArrayList<URI>();\n" + 
+					"	Application application;\n" + 
+					"}\n");
+			String testSource =
+					"package test;\n" + 
+					"\n" + 
+					"import java.io.*;\n" + 
+					"import java.net.*;\n" + 
+					"import java.util.*;\n" + 
+					"\n" + 
+					"import test.platform.*;\n" + 
+					"\n" + 
+					"public interface Application // extends Foo\n" + 
+					"{\n" + 
+					"}\n";
+			String testPath = "/bug/src/test/Application.java";
+			createFile(testPath, testSource);
+			// first compile: no error:
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			assertNoErrors();
+			char[] sourceChars = testSource.toCharArray();
+			this.problemRequestor.initialize(sourceChars);
+			getCompilationUnit(testPath).getWorkingCopy(this.wcOwner, null);
+			assertProblems(
+					"Unexpected problems",
+					"----------\n" + 
+					"1. WARNING in /bug/src/test/Application.java (at line 3)\n" + 
+					"	import java.io.*;\n" + 
+					"	       ^^^^^^^\n" + 
+					"The import java.io is never used\n" + 
+					"----------\n" + 
+					"2. WARNING in /bug/src/test/Application.java (at line 4)\n" + 
+					"	import java.net.*;\n" + 
+					"	       ^^^^^^^^\n" + 
+					"The import java.net is never used\n" + 
+					"----------\n" + 
+					"3. WARNING in /bug/src/test/Application.java (at line 5)\n" + 
+					"	import java.util.*;\n" + 
+					"	       ^^^^^^^^^\n" + 
+					"The import java.util is never used\n" + 
+					"----------\n" + 
+					"4. WARNING in /bug/src/test/Application.java (at line 7)\n" + 
+					"	import test.platform.*;\n" + 
+					"	       ^^^^^^^^^^^^^\n" + 
+					"The import test.platform is never used\n" + 
+					"----------\n",
+					this.problemRequestor);
+			// introduce error:
+			String testSourceEdited =
+					"package test;\n" + 
+					"\n" + 
+					"import java.io.*;\n" + 
+					"import java.net.*;\n" + 
+					"import java.util.*;\n" + 
+					"\n" + 
+					"import test.platform.*;\n" + 
+					"\n" + 
+					"public interface Application extends Foo\n" + 
+					"{\n" + 
+					"}\n";
+			editFile(testPath, testSourceEdited);
+			java10Project.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			IMarker[] markers = java10Project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "Foo cannot be resolved to a type", markers);
+		} finally {
+			if (java10Project != null)
+				deleteProject(java10Project);
+		}
+	}
+
 	protected void assertNoErrors() throws CoreException {
 		for (IProject p : getWorkspace().getRoot().getProjects()) {
 			int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index a8e5bd2..3c24b42 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -502,7 +502,7 @@
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (currentIndex < length) {
 			unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]);
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<length);
 			invocationSite.setFieldIndex(currentIndex);
 			if (binding == null) {
 				if (currentIndex == length) {
@@ -648,7 +648,7 @@
 	foundType : if (binding instanceof PackageBinding) {
 		while (currentIndex < length) {
 			PackageBinding packageBinding = (PackageBinding) binding;
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<length);
 			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/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index f0aa0d1..92275c1 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -536,7 +536,7 @@
 	foundNothingOrType: if (binding != null) {
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (i < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[i++], module);
+			binding = packageBinding.getTypeOrPackage(compoundName[i++], module, i<length);
 			if (binding instanceof ReferenceBinding && binding.problemId() == ProblemReasons.NotAccessible) {
 				return this.environment.convertToRawType((TypeBinding) binding, false /*do not force conversion of enclosing types*/);
 			}
@@ -607,7 +607,7 @@
 
 	char[] name = compoundName[compoundName.length - 1];
 	if (binding instanceof PackageBinding) {
-		Binding temp = ((PackageBinding) binding).getTypeOrPackage(name, module());
+		Binding temp = ((PackageBinding) binding).getTypeOrPackage(name, module(), false);
 		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
@@ -663,7 +663,7 @@
 
 	Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA);
 	if (importBinding != null)
-		importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1], module());
+		importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1], module(), false);
 
 	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/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index 0944230..d7d4555 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,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -233,7 +233,7 @@
 * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
 */
 
-public Binding getTypeOrPackage(char[] name, ModuleBinding mod) {
+public Binding getTypeOrPackage(char[] name, ModuleBinding mod, boolean splitPackageAllowed) {
 	ReferenceBinding problemBinding = null;
 	ReferenceBinding referenceBinding = getType0(name);
 	lookForType0:
@@ -255,6 +255,9 @@
 
 	PackageBinding packageBinding = getPackage0(name);
 	if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) {
+		if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
+			return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+		}
 		return packageBinding;
 	}
 	lookForType:
@@ -278,6 +281,9 @@
 
 	if (packageBinding == null) { // have not looked for it before
 		if ((packageBinding = findPackage(name, mod)) != null) {
+			if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
+				return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+			}
 			return packageBinding;
 		}
 		if (referenceBinding != null && referenceBinding != LookupEnvironment.TheNotFoundType) {
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 28ef21f..3734dd5 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -2977,7 +2977,7 @@
 		int currentIndex = 1, length = compoundName.length;
 		PackageBinding packageBinding = (PackageBinding) binding;
 		while (currentIndex < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<length);
 			if (binding == null) {
 				return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null /* no closest match since search for pkg*/, ProblemReasons.NotFound);
 			}
@@ -3048,7 +3048,7 @@
 		if (packageBinding == null)
 			return getType(name);
 
-		Binding binding = packageBinding.getTypeOrPackage(name, module());
+		Binding binding = packageBinding.getTypeOrPackage(name, module(), false);
 		if (binding == null) {
 			return new ProblemReferenceBinding(
 				CharOperation.arrayConcat(packageBinding.compoundName, name),
@@ -3104,7 +3104,7 @@
 		if (binding instanceof PackageBinding) {
 			PackageBinding packageBinding = (PackageBinding) binding;
 			while (currentIndex < typeNameLength) {
-				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module()); // does not check visibility
+				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<typeNameLength); // does not check visibility
 				if (binding == null) {
 					char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex);
 					return new ProblemReferenceBinding(
@@ -3325,7 +3325,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, module());
+			Binding binding = currentPackage.getTypeOrPackage(name, module(), false);
 			if (binding instanceof ReferenceBinding) {
 				ReferenceBinding referenceType = (ReferenceBinding) binding;
 				if ((referenceType.tagBits & TagBits.HasMissingType) == 0) {
@@ -3441,7 +3441,7 @@
 			PackageBinding packageBinding = (PackageBinding) binding;
 
 			while (currentIndex < nameLength) {
-				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module());
+				binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<nameLength);
 				if (binding == null)
 					return new ProblemReferenceBinding(
 						CharOperation.subarray(compoundName, 0, currentIndex),
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 d067d4b..d829d09 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,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -455,7 +455,7 @@
 		PackageBinding packageBinding = (PackageBinding) binding;
 
 		while (currentIndex < length) {
-			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], null);
+			binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], null, currentIndex<length);
 			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