Bug 527593 - [9] support launching modular projects with multiple output
folders
Change-Id: I12874713ed27a0cc17f1e7c06899cb6c0cf7c74d
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java
index 5e9e94a..8ec39fe 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java
@@ -10,11 +10,15 @@
*******************************************************************************/
package org.eclipse.jdt.internal.debug.ui.actions;
+import java.util.Set;
+
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchDelegate;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
-import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
@@ -71,7 +75,10 @@
fModuleArgumentsText.setText(str);
} else {
- fModuleArgumentsText.setText(JavaRuntime.getModuleCLIOptions(flaunchConfiguration));
+ AbstractJavaLaunchConfigurationDelegate delegate = getJavaLaunchConfigurationDelegate();
+ if (delegate != null) {
+ fModuleArgumentsText.setText(delegate.getModuleCLIOptions(flaunchConfiguration));
+ }
}
fOriginalText = fModuleArgumentsText.getText();
@@ -82,6 +89,19 @@
return comp;
}
+ public AbstractJavaLaunchConfigurationDelegate getJavaLaunchConfigurationDelegate() throws CoreException {
+ Set<String> modes = flaunchConfiguration.getModes();
+ modes.add(ILaunchManager.RUN_MODE);
+ AbstractJavaLaunchConfigurationDelegate delegate = null;
+ for (ILaunchDelegate launchDelegate : flaunchConfiguration.getType().getDelegates(modes)) {
+ if (launchDelegate.getDelegate() instanceof AbstractJavaLaunchConfigurationDelegate) {
+ delegate = (AbstractJavaLaunchConfigurationDelegate) launchDelegate.getDelegate();
+ break;
+ }
+ }
+ return delegate;
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.MessageDialog#buttonPressed(int)
*/
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
index 21b7d98..cefcb9a 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
@@ -18,8 +18,10 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
@@ -47,6 +49,7 @@
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
@@ -428,7 +431,8 @@
for (IRuntimeClasspathEntry entry : entries) {
String location = entry.getLocation();
if (location != null) {
- if (entry.getClasspathProperty() != IRuntimeClasspathEntry.MODULE_PATH) {
+ if (entry.getClasspathProperty() != IRuntimeClasspathEntry.MODULE_PATH
+ && entry.getClasspathProperty() != IRuntimeClasspathEntry.PATCH_MODULE) {
if (!set.contains(location)) {
userEntries.add(location);
set.add(location);
@@ -1117,9 +1121,53 @@
* <li>{@link IClasspathAttribute#PATCH_MODULE}</li>
* </ul>
*
+ * @throws CoreException
+ *
* @since 3.10
*/
- protected String getModuleCLIOptions(ILaunchConfiguration configuration) {
- return JavaRuntime.getModuleCLIOptions(configuration);
+ public String getModuleCLIOptions(ILaunchConfiguration configuration) throws CoreException {
+ String moduleCLIOptions = JavaRuntime.getModuleCLIOptions(configuration);
+
+ IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedRuntimeClasspath(configuration);
+ entries = JavaRuntime.resolveRuntimeClasspath(entries, configuration);
+ LinkedHashMap<String, String> moduleToLocations = new LinkedHashMap<>();
+
+ for (IRuntimeClasspathEntry entry : entries) {
+ String location = entry.getLocation();
+ if (location != null) {
+ if (entry.getClasspathProperty() == IRuntimeClasspathEntry.PATCH_MODULE) {
+ IJavaProject javaProject = entry.getJavaProject();
+ IModuleDescription moduleDescription = javaProject == null ? null : javaProject.getModuleDescription();
+ if (moduleDescription != null) {
+ String moduleName = moduleDescription.getElementName();
+ String locations = moduleToLocations.get(moduleName);
+ if (locations == null) {
+ moduleToLocations.put(moduleName, location);
+ } else {
+ moduleToLocations.put(moduleName, locations + File.pathSeparator + location);
+ }
+ } else {
+ // should not happen, log?
+ }
+ }
+ }
+ }
+ if (moduleToLocations.isEmpty()) {
+ return moduleCLIOptions;
+ }
+ StringBuilder sb = new StringBuilder(moduleCLIOptions);
+
+ for (Entry<String, String> entry : moduleToLocations.entrySet()) {
+ if (sb.length() > 0) {
+ sb.append(' ');
+ }
+ sb.append("--patch-module"); //$NON-NLS-1$
+ sb.append(' ');
+ sb.append(entry.getKey());
+ sb.append('=');
+ sb.append(entry.getValue());
+ }
+
+ return sb.toString();
}
}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
index 265c19d..64e0aa1 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
@@ -97,19 +97,26 @@
/**
* Classpath property identifier for entries that should appear on the module path for modular project.
- *
+ *
* @since 3.10
*/
public static final int MODULE_PATH = 4;
/**
* Classpath property identifier for entries that should appear on the class path for modular project.
- *
+ *
* @since 3.10
*/
public static final int CLASS_PATH = 5;
/**
+ * Classpath property identifier for entries that should appear as --patch-module argument for a modular project.
+ *
+ * @since 3.10
+ */
+ public static final int PATCH_MODULE = 6;
+
+ /**
* Returns this classpath entry's type. The type of a runtime classpath entry is
* identified by one of the following constants:
* <ul>
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index ec76f9c..8dab81c 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -1317,7 +1317,9 @@
}
}
}
- if (nonDefault.isEmpty()) {
+ boolean isModular = project.getModuleDescription() != null;
+ if (nonDefault.isEmpty() && !isModular) {
+ // return here only if non-modular, because patch-module might be needed otherwise
return null;
}
// add the default location if not already included
@@ -1329,11 +1331,20 @@
for (int i = 0; i < locations.length; i++) {
IClasspathEntry newEntry = JavaCore.newLibraryEntry(nonDefault.get(i), null, null);
locations[i] = new RuntimeClasspathEntry(newEntry);
- locations[i].setClasspathProperty(classpathProperty);
+ if (isModular && !containsModuleInfo(locations[i])) {
+ locations[i].setClasspathProperty(IRuntimeClasspathEntry.PATCH_MODULE);
+ ((RuntimeClasspathEntry) locations[i]).setJavaProject(project);
+ } else {
+ locations[i].setClasspathProperty(classpathProperty);
+ }
}
return locations;
}
+ private static boolean containsModuleInfo(IRuntimeClasspathEntry entry) {
+ return new File(entry.getLocation() + File.separator + "module-info.class").exists(); //$NON-NLS-1$
+ }
+
/**
* Returns resolved entries for the given entry in the context of the given
* Java project. If the entry is of kind