All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jdt.internal.core.ModuleUpdater Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2017, 2018 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;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdatesByKind;
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.
 * 

For patch-module and limit-modules see * org.eclipse.jdt.internal.core.builder.ModuleEntryProcessor.

*/ public class ModuleUpdater { private final JavaProject javaProoject; private final Map moduleUpdates = new HashMap<>(); public ModuleUpdater(JavaProject javaProject) { this.javaProoject = javaProject; } /** * Detects any ADD_EXPORTS or ADD_READS classpath attributes, parses the value, * and collects the resulting module updates. * @param entry a classpath entry of the current project. */ public void computeModuleUpdates(IClasspathEntry entry) throws JavaModelException { for (IClasspathAttribute attribute : entry.getExtraAttributes()) { String attributeName = attribute.getName(); String values = attribute.getValue(); // the attributes considered here may have multiple values separated by ':' if (attributeName.equals(IClasspathAttribute.ADD_EXPORTS)) { for (String value : values.split(":")) { // format: /=(,)* //$NON-NLS-1$ int slash = value.indexOf('/'); int equals = value.indexOf('='); if (slash != -1 && equals != -1) { String modName = value.substring(0, slash); char[] packName = value.substring(slash+1, equals).toCharArray(); char[][] targets = CharOperation.splitOn(',', value.substring(equals+1).toCharArray()); addModuleUpdate(modName, new IUpdatableModule.AddExports(packName, targets), UpdateKind.PACKAGE); } else { Util.log(IStatus.WARNING, "Invalid argument to add-exports: "+value); //$NON-NLS-1$ } } } else if (attributeName.equals(IClasspathAttribute.ADD_READS)) { for (String value : values.split(":")) { // format: = //$NON-NLS-1$ int equals = value.indexOf('='); if (equals != -1) { String srcMod = value.substring(0, equals); char[] targetMod = value.substring(equals+1).toCharArray(); addModuleUpdate(srcMod, new IUpdatableModule.AddReads(targetMod), UpdateKind.MODULE); } else { Util.log(IStatus.WARNING, "Invalid argument to add-reads: "+value); //$NON-NLS-1$ } } } else if (attributeName.equals(IClasspathAttribute.MODULE_MAIN_CLASS)) { IModuleDescription module = this.javaProoject.getModuleDescription(); if (module == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST)); addModuleUpdate(module.getElementName(), m -> m.setMainClassName(values.toCharArray()), UpdateKind.MODULE); } } } public void addModuleUpdate(String moduleName, Consumer update, UpdateKind kind) { UpdatesByKind updates = this.moduleUpdates.get(moduleName); if (updates == null) { this.moduleUpdates.put(moduleName, updates = new UpdatesByKind()); } updates.getList(kind, true).add(update); } /** * @see IModuleAwareNameEnvironment#applyModuleUpdates(IUpdatableModule, UpdateKind) */ public void applyModuleUpdates(IUpdatableModule compilerModule, UpdateKind kind) { char[] name = compilerModule.name(); if (name != ModuleBinding.UNNAMED) { // can't update the unnamed module UpdatesByKind updates = this.moduleUpdates.get(String.valueOf(name)); if (updates != null) { for (Consumer update : updates.getList(kind, false)) update.accept(compilerModule); } } } private static boolean containsNonModularDependency(IClasspathEntry[] entries) { for (IClasspathEntry e : entries) { if (e.getEntryKind() != IClasspathEntry.CPE_SOURCE && !((ClasspathEntry) e).isModular()) return true; } return false; } // Bug 520713: allow test code to access code on the classpath public void addReadUnnamedForNonEmptyClasspath(JavaProject project, IClasspathEntry[] expandedClasspath) throws JavaModelException { for (String moduleName : determineModulesOfProjectsWithNonEmptyClasspath(project, expandedClasspath)) { addModuleUpdate(moduleName, new IUpdatableModule.AddReads(ModuleBinding.ALL_UNNAMED), UpdateKind.MODULE); } } public static Set determineModulesOfProjectsWithNonEmptyClasspath(JavaProject project, IClasspathEntry[] expandedClasspath) throws JavaModelException { LinkedHashSet list = new LinkedHashSet<>(); if (containsNonModularDependency(expandedClasspath)) { IModuleDescription moduleDescription = project.getModuleDescription(); if (moduleDescription != null) { list.add(moduleDescription.getElementName()); } } for (IClasspathEntry e1 : expandedClasspath) { if (e1.getEntryKind() == IClasspathEntry.CPE_PROJECT) { Object target = JavaModel.getTarget(e1, true); if (target instanceof IProject) { IProject prereqProject = (IProject) target; if (JavaProject.hasJavaNature(prereqProject)) { JavaProject prereqJavaProject = (JavaProject) JavaCore.create(prereqProject); if (containsNonModularDependency(prereqJavaProject.getResolvedClasspath())) { IModuleDescription prereqModuleDescription = prereqJavaProject.getModuleDescription(); if (prereqModuleDescription != null) { list.add(prereqModuleDescription.getElementName()); } } } } } } return list; } public UpdatesByKind getUpdates(String moduleName) { return this.moduleUpdates.get(moduleName); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy