Bug 534884 - [9] Transitive project dependencies are missing when
launching on a modular JVM
Change-Id: I3aad368f8fa759d58b436b33db27129567f9e261
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
index 8dc2675..61d2ed5 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.launching;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@@ -22,6 +23,7 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
+import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
@@ -152,7 +154,7 @@
IClasspathEntry entry = JavaCore.newProjectEntry(getJavaProject().getProject().getFullPath());
List<Object> classpathEntries = new ArrayList<>(5);
List<IClasspathEntry> expanding = new ArrayList<>(5);
- expandProject(entry, classpathEntries, expanding, excludeTestCode);
+ expandProject(entry, classpathEntries, expanding, excludeTestCode, isExportedEntriesOnly(), getJavaProject(), false);
IRuntimeClasspathEntry[] runtimeEntries = new IRuntimeClasspathEntry[classpathEntries.size()];
for (int i = 0; i < runtimeEntries.length; i++) {
Object e = classpathEntries.get(i);
@@ -184,10 +186,16 @@
* a list of projects that have been or are currently being expanded (to detect cycles)
* @param excludeTestCode
* if true, test dependencies will be excluded
+ * @param exportedEntriesOnly
+ * if true, only add exported transitive dependencies
+ * @param rootProject
+ * the root project for which the classpath is computed
+ * @param isModularJVM
+ * if jvm is java 9 or later
* @exception CoreException
* if unable to expand the classpath
*/
- private void expandProject(IClasspathEntry projectEntry, List<Object> expandedPath, List<IClasspathEntry> expanding, boolean excludeTestCode) throws CoreException {
+ public static void expandProject(IClasspathEntry projectEntry, List<Object> expandedPath, List<IClasspathEntry> expanding, boolean excludeTestCode, boolean exportedEntriesOnly, IJavaProject rootProject, boolean isModularJVM) throws CoreException {
expanding.add(projectEntry);
// 1. Get the raw classpath
// 2. Replace source folder entries with a project entry
@@ -222,7 +230,7 @@
// add exported entries, as configured
if (classpathEntry.isExported()) {
unexpandedPath.add(classpathEntry);
- } else if (!isExportedEntriesOnly() || project.equals(getJavaProject())) {
+ } else if (!exportedEntriesOnly || project.equals(rootProject)) {
// add non exported entries from root project or if we are including all entries
unexpandedPath.add(classpathEntry);
}
@@ -239,7 +247,7 @@
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_PROJECT:
if (!expanding.contains(entry)) {
- expandProject(entry, expandedPath, expanding, excludeTestCode);
+ expandProject(entry, expandedPath, expanding, excludeTestCode, exportedEntriesOnly, rootProject, isModularJVM);
}
break;
case IClasspathEntry.CPE_CONTAINER:
@@ -248,7 +256,16 @@
if (container != null) {
switch (container.getKind()) {
case IClasspathContainer.K_APPLICATION:
- property = IRuntimeClasspathEntry.USER_CLASSES;
+ if (isModularJVM) {
+ if (Arrays.stream(entry.getExtraAttributes()).anyMatch(attribute -> IClasspathAttribute.MODULE.equals(attribute.getName())
+ && Boolean.TRUE.toString().equals(attribute.getValue()))) {
+ property = IRuntimeClasspathEntry.MODULE_PATH;
+ } else {
+ property = IRuntimeClasspathEntry.CLASS_PATH;
+ }
+ } else {
+ property = IRuntimeClasspathEntry.USER_CLASSES;
+ }
break;
case IClasspathContainer.K_DEFAULT_SYSTEM:
property = IRuntimeClasspathEntry.STANDARD_CLASSES;
@@ -305,6 +322,9 @@
break;
case IClasspathEntry.CPE_VARIABLE:
IRuntimeClasspathEntry r = JavaRuntime.newVariableRuntimeClasspathEntry(entry.getPath());
+ if (isModularJVM) {
+ adjustClasspathProperty(r, entry);
+ }
r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
if (!expandedPath.contains(r)) {
@@ -319,6 +339,9 @@
for (int i = 0; i < roots.length; i++) {
IPackageFragmentRoot root = roots[i];
r = JavaRuntime.newArchiveRuntimeClasspathEntry(root.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), entry.getExtraAttributes(), entry.isExported());
+ if (isModularJVM) {
+ adjustClasspathProperty(r, entry);
+ }
r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
if (!expandedPath.contains(r)) {
@@ -335,6 +358,18 @@
}
return;
}
+
+ public static void adjustClasspathProperty(IRuntimeClasspathEntry r, IClasspathEntry entry) {
+ if (r.getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
+ if (Arrays.stream(entry.getExtraAttributes()).anyMatch(attribute -> IClasspathAttribute.MODULE.equals(attribute.getName())
+ && Boolean.TRUE.toString().equals(attribute.getValue()))) {
+ r.setClasspathProperty(IRuntimeClasspathEntry.MODULE_PATH);
+ } else {
+ r.setClasspathProperty(IRuntimeClasspathEntry.CLASS_PATH);
+ }
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IRuntimeClasspathEntry2#isComposite()
*/
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 588c221..fc5c259 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
@@ -979,87 +979,42 @@
* @since 3.10
*/
public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeDependencies(IJavaProject project, boolean excludeTestCode) throws CoreException {
- List<IRuntimeClasspathEntry> classpathEntries = new ArrayList<>(3);
- if (!(project instanceof JavaProject)) {
- return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
- }
- JavaProject javaProject = (JavaProject) project;
- IClasspathEntry[] entries = javaProject.getExpandedClasspath(excludeTestCode);
-
IClasspathEntry entry1 = JavaCore.newProjectEntry(project.getProject().getFullPath());
- if (isModularProject(project)) {
- classpathEntries.add(new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.MODULE_PATH));
- } else {
- classpathEntries.add(new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.CLASS_PATH));
- }
- for (int i = 0; i < entries.length; i++) {
- IClasspathEntry entry = entries[i];
- switch (entry.getEntryKind()) {
- case IClasspathEntry.CPE_CONTAINER:
- IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
- if (container != null) {
- switch (container.getKind()) {
- case IClasspathContainer.K_APPLICATION:
- // don't look at application entries
- break;
- case IClasspathContainer.K_DEFAULT_SYSTEM:
- if (isModule(entry, project)) {
- classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.MODULE_PATH, project));
- } else {
- classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.CLASS_PATH, project));
- }
- break;
- case IClasspathContainer.K_SYSTEM:
- if (isModule(entry, project)) {
- classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.MODULE_PATH, project));
- } else {
- classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.CLASS_PATH, project));
- }
- break;
- }
- }
- break;
- case IClasspathEntry.CPE_PROJECT:
- String name = entry.getPath().lastSegment();
- IProject dep = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
- IJavaProject javaProject1 = JavaCore.create(dep);
- if (isModule(entry, project)) {
- classpathEntries.add(newProjectRuntimeClasspathEntry(javaProject1, IRuntimeClasspathEntry.MODULE_PATH));
+ List<Object> classpathEntries = new ArrayList<>(5);
+ List<IClasspathEntry> expanding = new ArrayList<>(5);
+ boolean exportedEntriesOnly = Platform.getPreferencesService().getBoolean(LaunchingPlugin.ID_PLUGIN, JavaRuntime.PREF_ONLY_INCLUDE_EXPORTED_CLASSPATH_ENTRIES, false, null);
+ DefaultProjectClasspathEntry.expandProject(entry1, classpathEntries, expanding, excludeTestCode, exportedEntriesOnly, project, true);
+ IRuntimeClasspathEntry[] runtimeEntries = new IRuntimeClasspathEntry[classpathEntries.size()];
+ for (int i = 0; i < runtimeEntries.length; i++) {
+ Object e = classpathEntries.get(i);
+ if (e instanceof IClasspathEntry) {
+ IClasspathEntry cpe = (IClasspathEntry) e;
+ if (cpe == entry1) {
+ if (isModularProject(project)) {
+ runtimeEntries[i] = new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.MODULE_PATH);
} else {
- classpathEntries.add(newProjectRuntimeClasspathEntry(javaProject1, IRuntimeClasspathEntry.CLASS_PATH));
+ runtimeEntries[i] = new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.CLASS_PATH);
}
- break;
- case IClasspathEntry.CPE_VARIABLE:
- if (JRELIB_VARIABLE.equals(entry.getPath().segment(0))) {
- IRuntimeClasspathEntry jre = newVariableRuntimeClasspathEntry(entry.getPath());
- jre.setClasspathProperty(IRuntimeClasspathEntry.MODULE_PATH);
- classpathEntries.add(jre);
- }
- break;
- case IClasspathEntry.CPE_LIBRARY:
- IPackageFragmentRoot root = project.findPackageFragmentRoot(entry.getPath());
- if (root != null && !root.getRawClasspathEntry().getPath().segment(0).contains("JRE_CONTAINER")) { //$NON-NLS-1$
- IRuntimeClasspathEntry r;
- if (JavaRuntime.isModule(entry, project)) {
- r = JavaRuntime.newArchiveRuntimeClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.MODULE_PATH);
- } else {
- r = JavaRuntime.newArchiveRuntimeClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.CLASS_PATH);
- }
- r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
- r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
- classpathEntries.add(r);
- }
- break;
- default:
- break;
+ } else {
+ runtimeEntries[i] = new RuntimeClasspathEntry(cpe);
+ DefaultProjectClasspathEntry.adjustClasspathProperty(runtimeEntries[i], cpe);
+ }
+ } else {
+ runtimeEntries[i] = (IRuntimeClasspathEntry) e;
}
}
-
+ List<IRuntimeClasspathEntry> ordered = new ArrayList<>(runtimeEntries.length);
+ for (int i = 0; i < runtimeEntries.length; i++) {
+ if (runtimeEntries[i].getClasspathProperty() != IRuntimeClasspathEntry.STANDARD_CLASSES
+ && runtimeEntries[i].getClasspathProperty() != IRuntimeClasspathEntry.BOOTSTRAP_CLASSES) {
+ ordered.add(runtimeEntries[i]);
+ }
+ }
IRuntimeClasspathEntry jreEntry = JavaRuntime.computeModularJREEntry(project);
if (jreEntry != null) { // With some jre stub jars don't have jre entries
- classpathEntries.add(jreEntry);
+ ordered.add(jreEntry);
}
- return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
+ return ordered.toArray(new IRuntimeClasspathEntry[ordered.size()]);
}
/**