blob: 587f64facff60f5cf802456a77d9ab251dfb1689 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 GK Software AG, and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Stephan Herrmann - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
import org.eclipse.jdt.internal.core.ClasspathEntry;
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
* @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(ClasspathEntry entry) {
String extraAttribute = ClasspathEntry.getExtraAttribute(entry, IClasspathAttribute.LIMIT_MODULES);
if (extraAttribute == null)
return null;
// collect the transitive closure of modules contained in limitSet
return new LinkedHashSet<>(Arrays.asList(extraAttribute.split(","))); //$NON-NLS-1$
}
}