Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2017-09-10 18:06:38 +0000
committerStephan Herrmann2017-09-11 19:00:41 +0000
commit9b8300bd40097f83910af2d40fdc1cb6ee0c88af (patch)
treee351157e74684935db5f54f6df0c0e5e472b6502
parent9228b527f2119ceb61b755b355bde00106082ec7 (diff)
downloadeclipse.jdt.core-9b8300bd40097f83910af2d40fdc1cb6ee0c88af.tar.gz
eclipse.jdt.core-9b8300bd40097f83910af2d40fdc1cb6ee0c88af.tar.xz
eclipse.jdt.core-9b8300bd40097f83910af2d40fdc1cb6ee0c88af.zip
Bug 522073: [9] core support for --limit-modules
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java81
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java17
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java74
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java143
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java87
8 files changed, 354 insertions, 64 deletions
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 01b88c51be..398656e3b8 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
@@ -46,8 +46,10 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.core.ClasspathAttribute;
import org.eclipse.jdt.internal.core.ClasspathEntry;
+import org.eclipse.jdt.internal.core.builder.ClasspathJrt;
import org.eclipse.jdt.internal.core.util.Messages;
import junit.framework.Test;
@@ -5417,7 +5419,84 @@ public class ModuleBuilderTests extends ModifyingResourceTests {
this.problemRequestor);
} finally {
- this.deleteProject("org.astro.patch");
+ this.deleteProject("mod.one.patch");
+ }
+ }
+ public void testLimitModules1() throws CoreException, IOException {
+ if (!isJRE9) return;
+ String save = System.getProperty("modules.to.load");
+ JRTUtil.reset();
+ ClasspathJrt.resetCaches();
+ try {
+ // allow for a few more than we are using via limit-modules:
+ System.setProperty("modules.to.load", "java.base,java.desktop,java.datatransfer,java.rmi,java.sql,java.prefs,java.xml");
+ IClasspathAttribute[] attributes = {
+ JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"),
+ JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, "java.base,java.desktop")
+ };
+ IJavaProject project = createJava9ProjectWithJREAttributes("org.astro", new String[]{"src", "src2"}, attributes);
+
+ String[] sources = {
+ "src/module-info.java",
+ "module org.astro {\n" +
+ " requires java.base;\n" +
+ " requires java.desktop;\n" +
+ " requires java.datatransfer;\n" + // within the closure of java.desktop
+ " requires java.sql;\n" + // not included
+ "}\n",
+ "src/org/astro/Test2.java",
+ "package org.astro;\n" +
+ "class Test2 {\n" +
+ " java.awt.Window window;\n" +
+ "}\n",
+ "src2/org/astro/Test3.java",
+ "package org.astro;\n" +
+ "class Test3 {\n" +
+ " java.awt.datatransfer.Clipboard clippy;\n" +
+ "}\n"
+ };
+ createSourceFiles(project, sources);
+
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "java.sql cannot be resolved to a module", // outside limited scope
+ markers);
+
+ this.problemRequestor.reset();
+ ICompilationUnit cu = getCompilationUnit("/org.astro/src/module-info.java");
+ cu.getWorkingCopy(this.wcOwner, null);
+ assertProblems(
+ "Unexpected problems",
+ "----------\n" +
+ "1. ERROR in /org.astro/src/module-info.java\n" +
+ "java.sql cannot be resolved to a module\n" +
+ "----------\n",
+ this.problemRequestor);
+
+ this.problemRequestor.reset();
+ cu = getCompilationUnit("/org.astro/src/org/astro/Test2.java");
+ cu.getWorkingCopy(this.wcOwner, null);
+ assertProblems(
+ "Unexpected problems",
+ "----------\n" +
+ "----------\n",
+ this.problemRequestor);
+
+ this.problemRequestor.reset();
+ cu = getCompilationUnit("/org.astro/src/org/astro/Test3.java");
+ cu.getWorkingCopy(this.wcOwner, null);
+ assertProblems(
+ "Unexpected problems",
+ "----------\n" +
+ "----------\n",
+ this.problemRequestor);
+
+ } finally {
+ this.deleteProject("org.astro");
+ System.setProperty("modules.to.load", save);
+ JRTUtil.reset();
+ ClasspathJrt.resetCaches();
}
}
protected void assertNoErrors() throws CoreException {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
index d26a30c1dd..cda9dbb643 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -123,6 +123,11 @@ public class JRTUtil {
return system;
}
+ /** TEST ONLY (use when changing the "modules.to.load" property). */
+ public static void reset() {
+ images = null;
+ }
+
/**
* Given the path of a modular image file, this method walks the archive content and
* notifies the supplied visitor about packages and files visited.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
index 6b2d5a6ace..0b25df9c19 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
@@ -172,6 +172,23 @@ public interface IClasspathAttribute {
String PATCH_MODULE = "patch-module"; //$NON-NLS-1$
/**
+ * Constant for the name of the limit-modules attribute.
+ *
+ * <p>The value of this attribute must be a comma-separated list of names of modules
+ * defined in the classpath entry, to which this attribute is attached.
+ * The set of modules observable through this entry will be limited to
+ * the transitive closure of modules in this list.</p>
+ *
+ * <p>This attribute is supported for classpath entries of kind
+ * {@link IClasspathEntry#CPE_CONTAINER}.
+ * A classpath entry having this attribute must also have the
+ * {@link #MODULE} attribute with value <code>"true"</code>.</p>
+ *
+ * @since 3.13 BETA_JAVA9
+ */
+ String LIMIT_MODULES = "limit-modules"; //$NON-NLS-1$
+
+ /**
* Constant of the name of the module-main-class attribute.
* The classpath entry holding this attribute must refer to a source folder
* containing the implementation of a module.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 914f902ba3..315631353e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 201y IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@ import java.net.URI;
import java.nio.file.FileVisitResult;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@@ -29,6 +30,7 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
@@ -79,6 +81,10 @@ import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.eval.IEvaluationContext;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
@@ -643,6 +649,9 @@ public class JavaProject
if (info.jrtRoots == null || !info.jrtRoots.containsKey(entryPath)) {
ObjectVector imageRoots = new ObjectVector();
loadModulesInJimage(entryPath, imageRoots, rootToResolvedEntries, resolvedEntry, referringEntry);
+ String limitModules = ClasspathEntry.getExtraAttribute(resolvedEntry, IClasspathAttribute.LIMIT_MODULES);
+ if (limitModules != null)
+ imageRoots = filterLimitedModules(entryPath, imageRoots, limitModules);
info.setJrtPackageRoots(entryPath, imageRoots);
accumulatedRoots.addAll(imageRoots);
rootIDs.add(rootID);
@@ -691,6 +700,69 @@ public class JavaProject
}
}
+ private ObjectVector filterLimitedModules(IPath jrtPath, ObjectVector imageRoots, String limitModules) {
+ Set<String> limitModulesSet = new HashSet<>(Arrays.asList(limitModules.split(","))); //$NON-NLS-1$
+ ModuleLookup lookup = new ModuleLookup(jrtPath.toFile());
+ // collect all module roots:
+ for (int i = 0; i < imageRoots.size(); i++) {
+ lookup.recordRoot((JrtPackageFragmentRoot) imageRoots.elementAt(i));
+ }
+ // for those contained in limitModules, add the transitive closure:
+ for (int i = 0; i < imageRoots.size(); i++) {
+ String moduleName = ((JrtPackageFragmentRoot) imageRoots.elementAt(i)).moduleName;
+ if (limitModulesSet.contains(moduleName))
+ lookup.addTransitive(moduleName);
+ }
+ // map the result back to package fragment roots:
+ ObjectVector result = new ObjectVector(lookup.resultModuleSet.size());
+ for (IModule mod : lookup.resultModuleSet) {
+ result.add(lookup.getRoot(mod));
+ }
+ return result;
+ }
+
+ /** Helper for computing the transitive closure of a set of modules. */
+ private static class ModuleLookup {
+ File jrtFile;
+ Map<String, JrtPackageFragmentRoot> modNames2Roots = new HashMap<>();
+ Map<String, IModule> modules = new HashMap<>();
+ Set<IModule> resultModuleSet = new HashSet<>();
+
+ public ModuleLookup(File jrtFile) {
+ this.jrtFile = jrtFile;
+ }
+
+ void recordRoot(JrtPackageFragmentRoot root) {
+ this.modNames2Roots.put(root.moduleName, root);
+ }
+ void addTransitive(String moduleName) {
+ IModule module = getModule(moduleName);
+ if (module != null && this.resultModuleSet.add(module)) {
+ for (IModuleReference reqRef : module.requires())
+ addTransitive(String.valueOf(reqRef.name()));
+ }
+ }
+ private IModule getModule(String moduleName) {
+ IModule result = this.modules.get(moduleName);
+ if (result == null) {
+ JrtPackageFragmentRoot root = this.modNames2Roots.get(moduleName);
+ if (root != null) {
+ try {
+ ClassFileReader classFile = JRTUtil.getClassfile(this.jrtFile, TypeConstants.MODULE_INFO_CLASS_NAME_STRING, root.moduleName);
+ result = classFile.getModuleDeclaration();
+ this.modules.put(moduleName, result);
+ } catch (IOException | ClassFormatException e) {
+ JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Failed to read module-info.class", e)); //$NON-NLS-1$
+ }
+ }
+ }
+ return result;
+ }
+ JrtPackageFragmentRoot getRoot(IModule module) {
+ return this.modNames2Roots.get(String.valueOf(module.name()));
+ }
+ }
+
/**
* This bogus package fragment root acts as placeholder plus bridge for the
* real one until the module name becomes available. It is useful in certain
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
index e570dc0e5f..0da310f22e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java
@@ -33,8 +33,10 @@ import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.core.util.Util;
/**
- * An instance of this class collects add-exports and add-reads options from a project's
- * class path entries, and performs the corresponding updates when requested by the compiler.
+ * An instance of this class collects <code>add-exports</code> and <code>add-reads</code> options from
+ * a project's class path entries, and performs the corresponding updates when requested by the compiler.
+ * <p>For <code>patch-module</code> and <code>limit-modules</code> see
+ * org.eclipse.jdt.internal.core.builder.ModuleEntryProcessor.</p>
*/
public class ModuleUpdater {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
index 45c8c7d6fb..97f430c138 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -271,4 +271,9 @@ public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageN
//
return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false);
}
+/** TEST ONLY */
+public static void resetCaches() {
+ PackageCache.clear();
+ ModulesCache.clear();
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java
new file mode 100644
index 0000000000..07736264fe
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModuleEntryProcessor.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
+import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
+import org.eclipse.jdt.internal.core.ClasspathEntry;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.JrtPackageFragmentRoot;
+import org.eclipse.jdt.internal.core.ModuleUpdater;
+
+/**
+ * Collection of functions to process classpath attributes relating to modules (from JEP 261).
+ * For <code>add-exports</code> and <code>add-reads</code> see {@link ModuleUpdater}.
+ */
+class ModuleEntryProcessor {
+
+ // ------------- patch-module: ---------------
+
+ /**
+ * Establish that an entry with <code>patch-module</code> appears at position 0, if any.
+ * This ensures that in the first iteration we find the patchedModule (see e.g., collectModuleEntries()),
+ * which later can be combined into each src-entry (see {@link #combinePatchIntoModuleEntry(ClasspathLocation, IModule, Map)}).
+ * @see IClasspathAttribute#PATCH_MODULE
+ */
+ static String pushPatchToFront(IClasspathEntry[] classpathEntries) {
+ String patchedModule = null;
+ for (int i = 0; i < classpathEntries.length; i++) {
+ IClasspathEntry entry = classpathEntries[i];
+ patchedModule = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.PATCH_MODULE);
+ if (patchedModule != null) {
+ if (i > 0) {
+ IClasspathEntry tmp = classpathEntries[0];
+ classpathEntries[0] = entry;
+ classpathEntries[i] = tmp;
+ }
+ return patchedModule;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Given that sourceLocation belongs to the project that patches another module, combine this source location
+ * into the existing {@link IModulePathEntry} for the module to be patched.
+ * @param sourceLocation source location of the patch project
+ * @param patchedModule module defined in the target location
+ * @param moduleEntries map of known module locations
+ */
+ static void combinePatchIntoModuleEntry(ClasspathLocation sourceLocation, IModule patchedModule, Map<String, IModulePathEntry> moduleEntries) {
+ sourceLocation.setModule(patchedModule);
+ String patchedModuleName = String.valueOf(patchedModule.name());
+ IModulePathEntry mainEntry = moduleEntries.get(patchedModuleName);
+ ClasspathLocation[] combinedLocations = null;
+ if (mainEntry instanceof ModulePathEntry.Multi) {
+ ((ModulePathEntry.Multi) mainEntry).addPatchLocation(sourceLocation);
+ return;
+ } else if (mainEntry instanceof ClasspathJrt) {
+ combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation };
+ moduleEntries.put(patchedModuleName, new ModulePathEntry.Multi(null, patchedModule, combinedLocations));
+ return;
+ } else if (mainEntry instanceof ModulePathEntry) {
+ ClasspathLocation[] mainLocs = ((ModulePathEntry) mainEntry).locations;
+ combinedLocations = Arrays.copyOf(mainLocs, mainLocs.length+1);
+ combinedLocations[combinedLocations.length-1] = sourceLocation;
+ } else if (mainEntry instanceof ClasspathLocation) {
+ combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation };
+ } else {
+ throw new IllegalStateException("Cannot patch the module of classpath entry "+mainEntry); //$NON-NLS-1$
+ }
+ moduleEntries.put(patchedModuleName, new ModulePathEntry(null, patchedModule, combinedLocations));
+ }
+
+ // ------------- limit-modules: ---------------
+
+ /**
+ * Reads a <code>limit-modules</code> attribute, and computes the transitive closure of requested modules.
+ * @param javaProject the current java project
+ * @param entry the classpath entry to process
+ * @return a set of module names or <code>null</code> if the classpath attribute was not set.
+ * @see IClasspathAttribute#LIMIT_MODULES
+ */
+ static Set<String> computeLimitModules(JavaProject javaProject, ClasspathEntry entry) {
+ String extraAttribute = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.LIMIT_MODULES);
+ if (extraAttribute == null)
+ return null;
+
+ // collect all modules of this CP entry:
+ Map<String, IModule> modules = new HashMap<>();
+ for (IPackageFragmentRoot root : javaProject.findPackageFragmentRoots(entry)) {
+ if (root instanceof JrtPackageFragmentRoot) {
+ IModule module = ((JrtPackageFragmentRoot) root).getModule();
+ if (module != null)
+ modules.put(String.valueOf(module.name()), module);
+ }
+ }
+
+ // collect the transitive closure of modules contained in limitSet
+ Set<String> limitSet = new HashSet<>(Arrays.asList(extraAttribute.split(","))); //$NON-NLS-1$
+ Set<String> result = new HashSet<>(limitSet);
+ for (Map.Entry<String, IModule> moduleEntry: modules.entrySet()) {
+ if (limitSet.contains(moduleEntry.getKey()))
+ addTransitive(moduleEntry.getValue(), modules, result);
+ }
+ return result;
+ }
+
+ private static void addTransitive(IModule module, Map<String, IModule> modules, Set<String> result) {
+ if (module.requires() != null) {
+ for (int i = 0; i < module.requires().length; i++) {
+ IModuleReference requires = module.requires()[i];
+ String requiredName = String.valueOf(requires.name());
+ if (result.add(requiredName)) {
+ IModule requiredModule = modules.get(requiredName);
+ if (requiredModule != null)
+ addTransitive(requiredModule, modules, result);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index b587d14648..2a7a9abec3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -118,7 +118,7 @@ private void computeClasspathLocations(
}
IModuleDescription mod = null;
- String patchedModuleName = pushPatchToFront(classpathEntries);
+ String patchedModuleName = ModuleEntryProcessor.pushPatchToFront(classpathEntries);
IModule patchedModule = null;
nextEntry : for (int i = 0, l = classpathEntries.length; i < l; i++) {
@@ -135,6 +135,12 @@ private void computeClasspathLocations(
if (target == null) continue nextEntry;
boolean isOnModulePath = isOnModulePath(entry);
+ Set<String> limitModules = ModuleEntryProcessor.computeLimitModules(javaProject, entry);
+ if (patchedModuleName != null && limitModules != null && !limitModules.contains(patchedModuleName)) {
+ // TODO(SHMOD) report an error
+ patchedModuleName = null;
+ }
+
if (this.moduleUpdater != null)
this.moduleUpdater.computeModuleUpdates(entry);
@@ -159,7 +165,7 @@ private void computeClasspathLocations(
entry.fullExclusionPatternChars(),
entry.ignoreOptionalProblems());
if (patchedModule != null) {
- combineIntoModuleEntry(sourceLocation, patchedModule, moduleEntries);
+ ModuleEntryProcessor.combinePatchIntoModuleEntry(sourceLocation, patchedModule, moduleEntries);
}
sLocations.add(sourceLocation);
continue nextEntry;
@@ -218,9 +224,11 @@ private void computeClasspathLocations(
ModulePathEntry projectEntry = new ModulePathEntry(prereqJavaProject.getPath(), info,
projectLocations.toArray(new ClasspathLocation[projectLocations.size()]));
String moduleName = String.valueOf(info.name());
- moduleEntries.put(moduleName, projectEntry);
- if (moduleName.equals(patchedModuleName))
- patchedModule = info;
+ if (limitModules == null || limitModules.contains(moduleName)) {
+ moduleEntries.put(moduleName, projectEntry);
+ if (moduleName.equals(patchedModuleName))
+ patchedModule = info;
+ }
}
continue nextEntry;
@@ -247,7 +255,8 @@ private void computeClasspathLocations(
// TODO: Ideally we need to do something like mapToModulePathEntry using the path and if it is indeed
// a module path entry, then add the corresponding entry here, but that would need the target platform
if (moduleEntries != null) {
- patchedModule = collectModuleEntries(bLocation, path, isOnModulePath, patchedModuleName, patchedModule, moduleEntries);
+ patchedModule = collectModuleEntries(bLocation, path, isOnModulePath,
+ limitModules, patchedModuleName, patchedModule, moduleEntries);
}
if (binaryLocationsPerProject != null) { // normal builder mode
IProject p = resource.getProject(); // can be the project being built
@@ -270,7 +279,8 @@ private void computeClasspathLocations(
ClasspathLocation bLocation = ClasspathLocation.forLibrary(path.toOSString(), accessRuleSet, externalAnnotationPath, isOnModulePath);
bLocations.add(bLocation);
if (moduleEntries != null) {
- patchedModule = collectModuleEntries(bLocation, path, isOnModulePath, patchedModuleName, patchedModule, moduleEntries);
+ patchedModule = collectModuleEntries(bLocation, path, isOnModulePath,
+ limitModules, patchedModuleName, patchedModule, moduleEntries);
}
}
continue nextEntry;
@@ -326,35 +336,14 @@ private void computeClasspathLocations(
this.modulePathEntries = moduleEntries;
}
-/**
- * Establish that an entry with --patch-module appears at position 0, if any.
- * This ensures that in the first iteration we find the patchedModule (see e.g., collectModuleEntries()),
- * which later can be combined into each src-entry (see combineIntoModuleEntry()).
- */
-private String pushPatchToFront(IClasspathEntry[] classpathEntries) {
- String patchedModule = null;
- for (int i = 0; i < classpathEntries.length; i++) {
- IClasspathEntry entry = classpathEntries[i];
- patchedModule = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.PATCH_MODULE);
- if (patchedModule != null) {
- if (i > 0) {
- IClasspathEntry tmp = classpathEntries[0];
- classpathEntries[0] = entry;
- classpathEntries[i] = tmp;
- }
- return patchedModule;
- }
- }
- return null;
-}
-
/** Returns the patched module if that is served by the current (binary) location. */
-IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean isOnModulePath,
+IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean isOnModulePath, Set<String> limitModules,
String patchedModuleName, IModule patchedModule, Map<String, IModulePathEntry> moduleEntries) {
if (bLocation instanceof IMultiModuleEntry) {
IMultiModuleEntry binaryModulePathEntry = (IMultiModuleEntry) bLocation;
for (String moduleName : binaryModulePathEntry.getModuleNames()) {
- moduleEntries.put(moduleName, binaryModulePathEntry);
+ if (limitModules == null || limitModules.contains(moduleName))
+ moduleEntries.put(moduleName, binaryModulePathEntry);
}
if (patchedModuleName != null) {
IModule module = binaryModulePathEntry.getModule(patchedModuleName.toCharArray());
@@ -367,41 +356,19 @@ IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean is
IModule module = binaryModulePathEntry.getModule();
if (module != null) {
String moduleName = String.valueOf(module.name());
- moduleEntries.put(moduleName, binaryModulePathEntry);
- if (patchedModuleName != null) {
- if (moduleName.equals(patchedModuleName))
- return module;
- // TODO(SHMOD): report problem: patchedModuleName didn't match a module from this location
+ if (limitModules == null || limitModules.contains(moduleName)) {
+ moduleEntries.put(moduleName, binaryModulePathEntry);
+ if (patchedModuleName != null) {
+ if (moduleName.equals(patchedModuleName))
+ return module;
+ // TODO(SHMOD): report problem: patchedModuleName didn't match a module from this location
+ }
}
}
}
return patchedModule;
}
-void combineIntoModuleEntry(ClasspathLocation sourceLocation, IModule patchedModule, Map<String, IModulePathEntry> moduleEntries) {
- sourceLocation.setModule(patchedModule);
- String patchedModuleName = String.valueOf(patchedModule.name());
- IModulePathEntry mainEntry = moduleEntries.get(patchedModuleName);
- ClasspathLocation[] combinedLocations = null;
- if (mainEntry instanceof ModulePathEntry.Multi) {
- ((ModulePathEntry.Multi) mainEntry).addPatchLocation(sourceLocation);
- return;
- } else if (mainEntry instanceof ClasspathJrt) {
- combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation };
- moduleEntries.put(patchedModuleName, new ModulePathEntry.Multi(null, patchedModule, combinedLocations));
- return;
- } else if (mainEntry instanceof ModulePathEntry) {
- ClasspathLocation[] mainLocs = ((ModulePathEntry) mainEntry).locations;
- combinedLocations = Arrays.copyOf(mainLocs, mainLocs.length+1);
- combinedLocations[combinedLocations.length-1] = sourceLocation;
- } else if (mainEntry instanceof ClasspathLocation) {
- combinedLocations = new ClasspathLocation[] { (ClasspathLocation) mainEntry, sourceLocation };
- } else {
- throw new IllegalStateException("Cannot patch the module of classpath entry "+mainEntry); //$NON-NLS-1$
- }
- moduleEntries.put(patchedModuleName, new ModulePathEntry(null, patchedModule, combinedLocations));
-}
-
protected boolean isOnModulePath(ClasspathEntry entry) {
return entry.isModular();
}

Back to the top