Fixed Bug 520858: [9] ECJ should not allow module source path without a
valid module-info

Change-Id: Ie1d2e54c07a54c4bae655b07da337ee6f3bbb256
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 1c608e9..fddda9c 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, 2017 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 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,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
@@ -126,7 +125,6 @@
 	public CompilationUnit[] getCompilationUnits() {
 		// This method is largely a copy of Main#getCompilationUnits()
 		if (this.compilationUnits == null) return EclipseCompilerImpl.NO_UNITS;
-		Map<String,CompilationUnit> pathToModCU = new HashMap<>();
 		HashtableOfObject knownFileNames = new HashtableOfObject();
 		ArrayList<CompilationUnit> units = new ArrayList<>();
 		for (int round = 0; round < 2; round++) {
@@ -160,21 +158,6 @@
 						};
 						units.add(cu);
 						this.javaFileObjectMap.put(cu, javaFileObject);
-						if (isModuleInfo) {
-							int lastSlash = CharOperation.lastIndexOf(File.separatorChar, cu.fileName);
-							if (lastSlash != -1) {
-								pathToModCU.put(String.valueOf(CharOperation.subarray(cu.fileName, 0, lastSlash)), cu);
-							}
-						} else {
-							for (Entry<String, CompilationUnit> entry : pathToModCU.entrySet()) {
-								Path modPath = Paths.get(entry.getKey());
-								Path cuPath = Paths.get(name);
-								while (cuPath != null && cuPath.startsWith(modPath)) {
-									cu.setModule(entry.getValue());
-									break;
-								}
-							}
-						}
 				}
 				i++;
 			}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
index e43e258..9946914 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 GK Software AG, and others.
+ * Copyright (c) 2017, 2018 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
@@ -62,19 +62,15 @@
 		}
 		// record module information in CUs:
 		CompilationUnit[] compilationUnits = Util.compilationUnits(testFiles);
-		CompilationUnit modCU = null;
 		for (int i = 0; i < compilationUnits.length; i++) {
 			char[] fileName = compilationUnits[i].getFileName();
 			String fileNameString = String.valueOf(compilationUnits[i].getFileName());
 			if (CharOperation.endsWith(fileName, TypeConstants.MODULE_INFO_FILE_NAME)) {
-				modCU = compilationUnits[i];
 				compilationUnits[i].module = moduleFiles.get(fileNameString);
 			} else {
 				String modName = this.file2module.get(fileNameString.replace(File.separator, "/"));
 				if (modName != null) {
 					compilationUnits[i].module = modName.toCharArray();
-					if (modCU != null)
-						compilationUnits[i].setModule(modCU);
 				}
 			}
 		}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index 417bee1..e5771e5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -22,6 +22,7 @@
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -83,7 +84,7 @@
 			boolean shouldFlushOutputDirectory)
 	{
 		runConformModuleTest(testFileNames, commandLine,
-				expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory, OUTPUT_DIR);
+				expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory, OUTPUT_DIR + File.separator + "javac");
 	}
 
 	void runConformModuleTest(List<String> testFileNames, StringBuffer commandLine,
@@ -150,7 +151,7 @@
 			String expectedFailureOutOutputString, String expectedFailureErrOutputString,
 			boolean shouldFlushOutputDirectory, String javacErrorMatch) {
 		runNegativeModuleTest(testFileNames, commandLine, expectedFailureOutOutputString,
-				expectedFailureErrOutputString, shouldFlushOutputDirectory, javacErrorMatch, OUTPUT_DIR);
+				expectedFailureErrOutputString, shouldFlushOutputDirectory, javacErrorMatch, OUTPUT_DIR + File.separator + "javac");
 	}
 
 	void runNegativeModuleTest(List<String> testFileNames, StringBuffer commandLine,
@@ -227,6 +228,10 @@
 				buf.append(" -source 9 ");
 				continue;
 			}
+			if (tokens[i].trim().equals("-8")) {
+				buf.append(" -source 1.8 ");
+				continue;
+			}
 			if (tokens[i].startsWith("-warn") || tokens[i].startsWith("-err") || tokens[i].startsWith("-info")) {
 				if (tokens[i].contains("exports") && !tokens[i].contains("-exports"))
 					buf.append(" -Xlint:exports ");
@@ -849,8 +854,7 @@
 			.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 + "\"");
+			.append("\" ");
 		runConformModuleTest(files,
 				buffer, 
 				"",
@@ -2613,7 +2617,7 @@
 				"",
 				"The package pm is accessible from more than one module: mod.y, mod.x\n",
 				false,
-				"package conflict");
+				"reads package pm from both");
 		buffer = new StringBuffer();
 		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
 			.append(" -9 ")
@@ -2627,7 +2631,7 @@
 				"",
 				"invalid module name: mod.z\n",
 				false,
-				"invalid module");
+				"module not found");
 	}
 	public void testPackageConflict6() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -2755,8 +2759,7 @@
 				"",
 				"The package pm is accessible from more than one module: mod.y, mod.x\n",
 				false,
-				"package conflict",
-				OUTPUT_DIR);
+				"reads package pm from both");
 	}
 	public void testPackageTypeConflict1() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -2829,8 +2832,7 @@
 			.append(" -9 ")
 			.append(" -classpath \"")
 			.append(Util.getJavaClassLibsAsString())
-			.append("\" ")
-			.append(" --module-source-path " + "\"" + directory + "\"");
+			.append("\" ");
 
 		runNegativeModuleTest(files, 
 				buffer,
@@ -2843,7 +2845,7 @@
 				"----------\n" +
 				"1 problem (1 error)\n",
 				false,
-				"not in a module");
+				"does not exist");
 	}
 	public void testMixedSourcepath() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -3262,8 +3264,7 @@
 			.append(" -classpath \"")
 			.append(Util.getJavaClassLibsAsString())
 			.append("\" ")
-			.append(" -err:exports")
-			.append(" --module-source-path " + "\"" + directory + "\"");
+			.append(" -err:exports");
 
 		runConformModuleTest(files, buffer,
 				"",
@@ -3294,13 +3295,12 @@
 		.append("-classNames mod.one/p.XYZ")
 		.append(" --module-source-path " + "\"" + srcDir + "\"");
 
-		runNegativeModuleTest(files,
-				buffer,
+		files.forEach(name -> buffer.append(" \"" + name + "\""));
+		runNegativeTest(new String[0],
+				buffer.toString(),
 				"",
 				"invalid class name: mod.one/p.XYZ\n",
-				false,
-				"", // not expected pass with Javac
-				outDir);
+				false);
 	}
 	public void testBug518295b() {
 		Util.flushDirectoryContent(new File(OUTPUT_DIR));
@@ -3326,13 +3326,12 @@
 		.append("-classNames mod.xyz/p.X")
 		.append(" --module-source-path " + "\"" + srcDir + "\"");
 
-		runNegativeModuleTest(files,
-				buffer,
+		files.forEach(name -> buffer.append(" \"" + name + "\""));
+		runNegativeTest(new String[0],
+				buffer.toString(),
 				"",
 				"invalid module name: mod.xyz\n",
-				false,
-				"", // not expected pass with Javac
-				outDir);
+				false);
 	}
 	public void testBug518295c() {
 		Util.flushDirectoryContent(new File(OUTPUT_DIR));
@@ -3471,7 +3470,7 @@
 				"",
 				"module name mod._3_ does not match expected name mod.three\n",
 				false,
-				outDir);
+				"does not match expected name");
 	}
 	/*
 	 * Disabled because the parser seem to take the module path as mod and not mod.e 
@@ -3700,12 +3699,7 @@
 			.append(moduleLoc + File.separator + "module-info.java");
 
 		Set<String> classFiles = runConformModuleTest(
-				new String[] {
-					"mod.one/module-info.java",
-					"module mod.one { \n" +
-					"	requires java.sql;\n" +
-					"}"
-				},
+				new String[0],
 				buffer.toString(),
 				"",
 				"",
@@ -3729,10 +3723,10 @@
 						"}");
 		StringBuffer buffer = new StringBuffer();
 		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -8")
 			.append(" -classpath \"")
 			.append(Util.getJavaClassLibsAsString())
-			.append("\" ")
-			.append(" --module-source-path " + "\"" + directory + "\"");
+			.append("\" ");
 
 		runNegativeModuleTest(files, 
 				buffer,
@@ -3760,7 +3754,7 @@
 				"----------\n" + 
 				"4 problems (4 errors)\n",
 				false,
-				OUTPUT_DIR + File.separator + out);
+				"modules are not supported");
 	}
 	public void testBug522472c() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -4251,7 +4245,7 @@
 				"----------\n" + 
 				"1 problem (1 error)\n",
 				false,
-				"is not accessible to clients");
+				"module not found");
 	}
 	public void testLimitModules2() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -4290,7 +4284,7 @@
 				"----------\n" + 
 				"1 problem (1 error)\n",
 				false,
-				"is not accessible to clients");
+				"is not visible");
 	}
 	public void testLimitModules3() {
 		File outputDirectory = new File(OUTPUT_DIR);
@@ -4523,9 +4517,9 @@
 			.append(" -classpath \"")
 			.append(Util.getJavaClassLibsAsString())
 			.append("\" ");
-
-		runConformModuleTest(files,
-				buffer, 
+		files.forEach(name -> buffer.append(" \"" + name + "\""));
+		runConformTest(new String[0],
+				buffer.toString(), 
 				"",
 				"",
 				false);
@@ -4549,4 +4543,229 @@
 				"}";
 		checkDisassembledClassFile(OUTPUT_DIR + File.separator + out + File.separator + "module-info.class", "module-info", expectedOutput);
 	}
+	public void testBug520858() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module test {\n" +
+						"	requires org.astro;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ");
+		runConformModuleTest(files, buffer,
+				"",
+				"",
+				false);
+	}
+	public void testBug520858a() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module test {\n" +
+						"	requires org.astro;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ")
+			.append(srcDir + File.separator + "test" + File.separator + "p" + File.separator + "Test.java");
+		runConformModuleTest(Collections.emptyList(), buffer,
+				"",
+				"",
+				false);
+	}
+	public void testBug520858b() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module test {\n" +
+						"	requires org.astro;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ")
+			.append(srcDir + File.separator + "test" + File.separator + "p" + File.separator + "Test.java ")
+			.append(srcDir + File.separator + "test" + File.separator + "module-info.java ")
+			.append(srcDir + File.separator + "org.astro" + File.separator + "org" + File.separator + "astro" + File.separator + "World.java");
+		runConformModuleTest(Collections.emptyList(), buffer,
+				"",
+				"",
+				false);
+	}
+	public void testBug520858c() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ");
+		runNegativeModuleTest(files, buffer,
+				"",
+				"\'---OUTPUT_DIR_PLACEHOLDER---/src/test/p/Test.java\' does not belong to a module on the module source path\n", 
+				false,
+				"not in a module on the module source path");
+	}
+	public void testBug520858d() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ")
+			.append(srcDir + File.separator + "org.astro" + File.separator + "org" + File.separator + "astro" + File.separator + "World.java ")
+			.append(srcDir + File.separator + "test" + File.separator + "p" + File.separator + "Test.java");
+		runNegativeModuleTest(Collections.emptyList(), buffer,
+			"",
+			"\'---OUTPUT_DIR_PLACEHOLDER---/src/test/p/Test.java\' does not belong to a module on the module source path\n", 
+			false,
+			"not in a module on the module source path");
+	}
+	public void testBug520858e() {
+		Util.flushDirectoryContent(new File(OUTPUT_DIR));
+		String outDir = OUTPUT_DIR + File.separator + "bin";
+		String srcDir = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = srcDir + File.separator + "test";
+		List<String> files = new ArrayList<>(); 
+
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "Test.java", 
+			"package p;\n" +
+			"import org.astro.World;\n" + 
+			"public class Test {\n" +
+			"	World w = null;\n" +
+			"}");
+		moduleLoc = srcDir + File.separator + "org.astro";
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+				"module org.astro {\n" +
+				"	exports org.astro;\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "org" + File.separator + "astro", "World.java", 
+			"package org.astro;\n" +
+			"public interface World {\n" + 
+			"	public static String name() {\n" + 
+			"		return \"\";\n" + 
+			"	}\n" + 
+			"}");
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + outDir )
+			.append(" -source 9 ")
+			.append(" --module-source-path " + "\"" + srcDir + "\" ")
+			.append(srcDir + File.separator + "org.astro" + File.separator + "org" + File.separator + "astro" + File.separator + "World.java ")
+			.append(srcDir + File.separator + "org.astro" + File.separator + "module-info.java ")
+			.append(srcDir + File.separator + "test" + File.separator + "p" + File.separator + "Test.java");
+		runNegativeModuleTest(Collections.emptyList(), buffer,
+			"",
+			"\'---OUTPUT_DIR_PLACEHOLDER---/src/test/p/Test.java\' does not belong to a module on the module source path\n", 
+			false,
+			"not in a module on the module source path");
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests9.java
index d2d8cda..b6b3a1e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests9.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests9.java
@@ -75,7 +75,7 @@
 				"	exports org.eclipse.jdt.annotation;\n" +
 				"}\n",
 
-				"org/eclipse.jdt.annotation/DefaultLocation.java",
+				"org/eclipse/jdt/annotation/DefaultLocation.java",
 				"package org.eclipse.jdt.annotation;\n" + 
 				"\n" + 
 				"public enum DefaultLocation {\n" + 
@@ -162,19 +162,15 @@
 		}
 		// record module information in CUs:
 		CompilationUnit[] compilationUnits = Util.compilationUnits(testFiles);
-		CompilationUnit modCU = null;
 		for (int i = 0; i < compilationUnits.length; i++) {
 			char[] fileName = compilationUnits[i].getFileName();
 			String fileNameString = String.valueOf(compilationUnits[i].getFileName());
 			if (CharOperation.endsWith(fileName, TypeConstants.MODULE_INFO_FILE_NAME)) {
-				modCU = compilationUnits[i];
-				compilationUnits[i].module = moduleFiles.get(fileNameString);
+				compilationUnits[i].module = moduleFiles.get(fileNameString.replace(File.separator, "/"));
 			} else {
-				String modName = this.file2module.get(fileNameString);
+				String modName = this.file2module.get(fileNameString.replace(File.separator, "/"));
 				if (modName != null) {
 					compilationUnits[i].module = modName.toCharArray();
-					if (modCU != null)
-						compilationUnits[i].setModule(modCU);
 				}
 			}
 		}
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 dddfa46..c18e256 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, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -192,7 +192,7 @@
 			}
 		} else {
 			if (modCU != null)
-				units[i].setModule(modCU);
+				units[i].module = modCU.getModuleName();
 		}
 	}
 	return units;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java
index 68f6b6b..543dcc7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java
@@ -103,11 +103,12 @@
 			getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
 
 			markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			Arrays.sort(markers, (a,b) -> a.getAttribute(IMarker.CHAR_START, 0) - b.getAttribute(IMarker.CHAR_START, 0));
 			assertMarkers("Unexpected markers",
-					"java.desktop cannot be resolved to a module\n" + 
-					"java.datatransfer cannot be resolved to a module\n" + 
 					"java.awt cannot be resolved to a type\n" + 
-					"java.awt cannot be resolved to a type",
+					"java.awt cannot be resolved to a type\n" +
+					"java.desktop cannot be resolved to a module\n" + 
+					"java.datatransfer cannot be resolved to a module",
 					markers);
 		} finally {
 			this.deleteProject("org.astro");
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 ad6e6af..a92bd99 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -123,15 +123,13 @@
 		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),
+			return new NameEnvironmentAnswer(unit,
 					fetchAccessRestriction(qualifiedBinaryFileName));
 		String fullBinaryPath = this.path + qualifiedBinaryFileName;
 		long binaryModified = new File(fullBinaryPath).lastModified();
 		long sourceModified = new File(fullSourcePath).lastModified();
 		if (sourceModified > binaryModified)
-			return new NameEnvironmentAnswer(new CompilationUnit(null,
-					fullSourcePath, this.encoding, this.destinationPath),
+			return new NameEnvironmentAnswer(unit,
 					fetchAccessRestriction(qualifiedBinaryFileName));
 	}
 	if (binaryExists) {
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 50ad6f7..6a2893f 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,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -17,7 +17,6 @@
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
@@ -36,7 +35,6 @@
 		// else: use as the path of the directory into which class files must
 		//       be written.
 	private boolean ignoreOptionalProblems;
-	private CompilationUnit modCU;
 	private ModuleBinding moduleBinding;
 
 public CompilationUnit(char[] contents, String fileName, String encoding) {
@@ -112,9 +110,6 @@
 public String toString() {
 	return "CompilationUnit[" + new String(this.fileName) + "]";  //$NON-NLS-2$ //$NON-NLS-1$
 }
-public void setModule(CompilationUnit compilationUnit) {
-	this.modCU = compilationUnit;
-}
 @Override
 public char[] getModuleName() {
 	return this.module;
@@ -123,15 +118,10 @@
 public ModuleBinding module(LookupEnvironment rootEnvironment) {
 	if (this.moduleBinding != null)
 		return this.moduleBinding;
-	if (this.modCU != null)
-		return this.moduleBinding = this.modCU.module(rootEnvironment);
-	if (CharOperation.endsWith(this.fileName, TypeConstants.MODULE_INFO_FILE_NAME)) {
-		this.moduleBinding = rootEnvironment.getModule(this.module);
-		if (this.moduleBinding == null)
-			throw new IllegalStateException("Module should be known"); //$NON-NLS-1$
-		return this.moduleBinding;
-	}
-	return rootEnvironment.UnNamedModule;
+	this.moduleBinding = rootEnvironment.getModule(this.module);
+	if (this.moduleBinding == null)
+		throw new IllegalStateException("Module should be known"); //$NON-NLS-1$
+	return this.moduleBinding;
 }
 @Override
 public String getDestinationPath() {
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 0185aa1..d6ee3f1 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 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
@@ -3356,8 +3356,6 @@
 	if (Util.EMPTY_STRING.equals(defaultEncoding))
 		defaultEncoding = null;
 	
-	Map<String,CompilationUnit> pathToModCU = new HashMap<>();
-
 	for (int round = 0; round < 2; round++) {
 		for (int i = 0; i < fileCount; i++) {
 			char[] charName = this.filenames[i].toCharArray();
@@ -3382,19 +3380,6 @@
 				units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i],
 						shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()), 
 						this.modNames[i]);
-				if (isModuleInfo) {
-					int lastSlash = CharOperation.lastIndexOf(File.separatorChar, units[i].fileName);
-					if (lastSlash != -1) {
-						pathToModCU.put(String.valueOf(CharOperation.subarray(units[i].fileName, 0, lastSlash)), units[i]);
-					}
-				} else {
-					for (Entry<String, CompilationUnit> entry : pathToModCU.entrySet()) {
-						if (fileName.startsWith(entry.getKey())) { // associate CUs to module by common prefix
-							units[i].setModule(entry.getValue());
-							break;
-						}
-					}
-				}
 			}
 		}
 	}
@@ -3576,12 +3561,18 @@
 							}
 						} catch (IOException e) {
 							// Files doesn't exist and perhaps doesn't belong in a module, move on to other files
+							// Use empty module name to distinguish from missing module case
+							this.modNames[j] = ""; //$NON-NLS-1$
 						}
 					}
 				}
 			}
 		}
-		
+		for(int j = 0; j < this.filenames.length; j++) {
+			if (this.modNames[j] == null) {
+				throw new IllegalArgumentException(this.bind("configure.notOnModuleSourcePath", new String[] {this.filenames[j]})); //$NON-NLS-1$
+			}
+		}
 	}
 	return result;
 }
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 2049e89..1ee5d42 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2017 IBM Corporation and others.
+# Copyright (c) 2000, 2018 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
@@ -97,6 +97,7 @@
 configure.invalidInfo = invalid info token: ''{0}''. Ignoring this info token and compiling
 configure.invalidInfoOption = invalid info option: ''{0}''. Must specify an info token
 
+configure.notOnModuleSourcePath = ''{0}'' does not belong to a module on the module source path
 
 ## configure.directoryNotExist = directory does not exist: {0}
 configure.unrecognizedOption = Unrecognized option : {0}