Bug 546797 - [9][build path] Polish the new UI for modularity details
- textual rendering of patch-module (with absolute paths)
- explanation label in the Show JPMS Options dialog
- dis/enablement for the new button
- text polish
- robustness wrt closed projects
- offer to add system modules needed for add-reads
- offer tab switching from add-reads and remove(module)
- split module search (for correctness & speed):
- system modules only via the projects JRE entry
- only non-system modules via workspace search
- when current project is a patch, show the patched module as focus mod
- required: improved CPListElement.{hashCode,equals}
- polish null return vs. exception
- create module attribute on source folder of focus project if needed
Change-Id: I379ecdee3b3116820af5fc15fae6873542723852
Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java
index d066b1f..20c3ff7 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java
@@ -517,6 +517,7 @@
public static String ModuleDependenciesPage_modules_label;
public static String ModuleDependenciesPage_addSystemModule_button;
public static String ModuleDependenciesPage_details_label;
+ public static String ModuleDependenciesPage_nonModularProject_dummy;
// buttons:
public static String ModuleDependenciesPage_modules_remove_button;
public static String ModuleDependenciesPage_modules_read_button;
@@ -525,19 +526,28 @@
public static String ModuleDependenciesPage_modules_edit_button;
public static String ModuleDependenciesPage_showJPMSOptions_button;
// dialogs:
- public static String ModuleSelectionDialog_add_button;
- public static String ModuleSelectionDialog_addSystemModules_message;
public static String ModuleSelectionDialog_addSystemModules_title;
+ public static String ModuleSelectionDialog_addSystemModules_message;
+ public static String ModuleSelectionDialog_selectAll_button;
+ public static String ModuleSelectionDialog_add_button;
+
public static String ModuleSelectionDialog_selectModule_title;
public static String ModuleSelectionDialog_selectReadModule_message;
public static String ModuleSelectionDialog_searchModules_job;
public static String ModuleSelectionDialog_searchModules_temp_message;
- public static String ModuleSelectionDialog_selectAll_button;
+
+ public static String ModuleDependenciesAdapter_addSystemModule_title;
+ public static String ModuleDependenciesAdapter_addSystemModules_question;
+ public static String ModuleDependenciesAdapter_add_button;
+ public static String ModuleDependenciesAdapter_addReadsNotOnModulepath_error;
+ public static String ModuleDependenciesAdapter_goToLibrariesTab_button;
+ public static String ModuleDependenciesAdapter_goToProjectsTab_button;
public static String ModulePatchSourceSelectionDialog_patchSourceLocation_message;
public static String ModulePatchSourceSelectionDialog_patchSourceLocation_title;
public static String ShowJPMSOptionsDialog_dialog_title;
+ public static String ShowJPMSOptionsDialog_explanation_label;
public static String ShowJPMSOptionsDialog_close_button;
public static String ShowJPMSOptionsDialog_copyAndCopy_button;
public static String ShowJPMSOptionsDialog_empty_message;
@@ -547,17 +557,17 @@
public static String ModuleDependenciesPage_removingModule_message;
public static String ModuleDependenciesPage_removingModuleTransitive_message;
public static String ModuleDependenciesPage_remove_button;
- public static String ModuleDependenciesPage_cancel_button;
- public static String ModuleDependenciesPage_nonModularProject_dummy;
public static String ModuleDependenciesPage_removeCurrentModule_error;
public static String ModuleDependenciesPage_removeModule_error_with_hint;
public static String ModuleDependenciesPage_removeSystemModule_error_hint;
+
public static String ModuleDependenciesAdapter_patchConflict_title;
public static String ModuleDependenciesAdapter_patchConflict_message;
public static String ModuleDependenciesAdapter_patchOutputConflict_validationError;
public static String ModuleDependenciesAdapter_project_kind;
public static String ModuleDependenciesAdapter_sourceFolder_kind;
public static String ModuleDependenciesAdapter_configure_error;
+
// detail tree:
public static String ModuleDependenciesAdapter_declared_node;
public static String ModuleDependenciesAdapter_configured_node;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties
index b7a480e..0d508cf 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties
@@ -552,30 +552,40 @@
AddReadsBlock_targetModule_label=Target module
ModuleDependenciesPage_modules_label=All Modules
-ModuleDependenciesPage_addSystemModule_button=Add System Module...
+ModuleDependenciesPage_addSystemModule_button=Add S&ystem Module...
ModuleDependenciesPage_details_label=Details
+ModuleDependenciesPage_nonModularProject_dummy=Non-modular Project
# buttons
ModuleDependenciesPage_modules_remove_button=&Remove
ModuleDependenciesPage_modules_read_button=Rea&d Module...
ModuleDependenciesPage_modules_expose_package_button=E&xpose Package...
-ModuleDependenciesPage_modules_patch_button=&Patch with...
+ModuleDependenciesPage_modules_patch_button=Patch &with...
ModuleDependenciesPage_modules_edit_button=&Edit...
ModuleDependenciesPage_showJPMSOptions_button=Show &JPMS Options...
# dialogs:
-ModuleSelectionDialog_add_button=&Add
+ModuleSelectionDialog_addSystemModules_title=Select system modules to add
ModuleSelectionDialog_addSystemModules_message=Select modules to be added to the module path.\n\
Transitively required modules will be automatically selected.
-ModuleSelectionDialog_addSystemModules_title=Select system modules to add
+ModuleSelectionDialog_selectAll_button=&Select all
+ModuleSelectionDialog_add_button=&Add
+
ModuleSelectionDialog_selectModule_title=Select module
ModuleSelectionDialog_selectReadModule_message=Select module to read
ModuleSelectionDialog_searchModules_job=Searching modules in workspace
ModuleSelectionDialog_searchModules_temp_message=Searching modules in workspace...
-ModuleSelectionDialog_selectAll_button=Select all
+
+ModuleDependenciesAdapter_addSystemModule_title=Add System Modules
+ModuleDependenciesAdapter_addSystemModules_question=The following system modules are not included, add them now?\n
+ModuleDependenciesAdapter_add_button=&Add
+ModuleDependenciesAdapter_addReadsNotOnModulepath_error=The module ''{0}'' must be added to the Modulepath before a reads edge can be created to it
+ModuleDependenciesAdapter_goToLibrariesTab_button=&Go to Libraries tab
+ModuleDependenciesAdapter_goToProjectsTab_button=&Go to Projects tab
ModulePatchSourceSelectionDialog_patchSourceLocation_message=Select source locations (projects or source folders) that should be associated with the selected module ''{0}''
ModulePatchSourceSelectionDialog_patchSourceLocation_title=Select source locations for patching
ShowJPMSOptionsDialog_dialog_title=JPMS Options
+ShowJPMSOptionsDialog_explanation_label=Translation of all module-related options into the command line syntax as specified by the Java Platform Module System (JPMS):
ShowJPMSOptionsDialog_close_button=&Close
ShowJPMSOptionsDialog_copyAndCopy_button=C&opy && Close
ShowJPMSOptionsDialog_empty_message=<no JPMS options configured>
@@ -584,16 +594,15 @@
ModuleDependenciesPage_removeModule_dialog_title=Remove Module
ModuleDependenciesPage_removingModule_message=Removing module ''{0}''
ModuleDependenciesPage_removingModuleTransitive_message=Removing module ''{0}'' and modules depending on it:\n
-ModuleDependenciesPage_remove_button=Remove
-ModuleDependenciesPage_cancel_button=Cancel
-ModuleDependenciesPage_nonModularProject_dummy=Non-modular Project
+ModuleDependenciesPage_remove_button=&Remove
ModuleDependenciesPage_removeCurrentModule_error=Cannot remove the current module
ModuleDependenciesPage_removeModule_error_with_hint=Cannot remove module ''{0}''{1}
ModuleDependenciesPage_removeSystemModule_error_hint=\nOnly system modules can be removed here.\n\
-To remove other modules please remove them from the ModulePath (tab Projects or Libraries).
+To remove other modules please remove them from the Modulepath (Projects or Libraries tab).
+
+ModuleDependenciesAdapter_patchConflict_title=Patch module conflict
ModuleDependenciesAdapter_patchConflict_message=The {0} {1} was declared to patch module ''{2}''.\n\
Do you want to remove this and associate {3} with module ''{4}'' instead?
-ModuleDependenciesAdapter_patchConflict_title=Patch module conflict
ModuleDependenciesAdapter_patchOutputConflict_validationError=The following source locations cannot patch different modules because they share the same output location: {0}
ModuleDependenciesAdapter_project_kind=project
ModuleDependenciesAdapter_sourceFolder_kind=source folder
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathBasePage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathBasePage.java
index 76f06ba..95ee69d 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathBasePage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathBasePage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -344,7 +344,17 @@
}
}
-
+ protected void selectRootNode(TreeListDialogField<CPListElement> list, boolean modulePath) {
+ for (CPListElement cpListElement : list.getElements()) {
+ if (cpListElement instanceof RootCPListElement) {
+ RootCPListElement root= (RootCPListElement) cpListElement;
+ if (root.isModulePathRootNode() == modulePath) {
+ list.selectElements(new StructuredSelection(root));
+ return;
+ }
+ }
+ }
+ }
protected abstract class CPListAdapter implements IDialogFieldListener, ITreeListAdapter<CPListElement> {
private final Object[] EMPTY_ARR= new Object[0];
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathsBlock.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathsBlock.java
index 5aa1dc4..8bb52ab 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathsBlock.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathsBlock.java
@@ -272,7 +272,7 @@
item.setData(ordpage);
item.setControl(ordpage.getControl(folder));
- fModulesPage= new ModuleDependenciesPage(fContext, fClassPathList, fPageContainer);
+ fModulesPage= new ModuleDependenciesPage(fContext, fClassPathList);
item= new TabItem(folder, SWT.NONE);
item.setText(NewWizardMessages.BuildPathsBlock_tab_modules);
item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_MODULE));
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
index cab371b..a3c475e 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -599,7 +599,15 @@
public boolean equals(Object other) {
if (other != null && other.getClass().equals(getClass())) {
CPListElement elem= (CPListElement) other;
- return getClasspathEntry().equals(elem.getClasspathEntry());
+ if (!getClasspathEntry().equals(elem.getClasspathEntry())) {
+ return false;
+ }
+ if (this.fModule != null && elem.fModule != null) {
+ if (!this.fModule.equals(elem.fModule)) {
+ return false;
+ }
+ }
+ return this.fModule == null && elem.fModule == null;
}
return false;
}
@@ -611,7 +619,11 @@
public int hashCode() {
if(fPath==null)
return super.hashCode();
- return fPath.hashCode() + fEntryKind;
+ int code= fPath.hashCode() + fEntryKind;
+ if (this.fModule != null) {
+ code= 31 * code + this.fModule.hashCode();
+ }
+ return code;
}
@Override
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
index 97788d5..4f51da3 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -1439,4 +1439,7 @@
fLibrariesList.setFocus();
}
+ public void selectRootNode(boolean modulePath) {
+ selectRootNode(fLibrariesList, modulePath);
+ }
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesAdapter.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesAdapter.java
index 973b243..e5a47e3 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesAdapter.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesAdapter.java
@@ -16,6 +16,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -43,6 +44,7 @@
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.TreeViewer;
@@ -57,6 +59,7 @@
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.provisional.JavaModelAccess;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
@@ -314,6 +317,12 @@
possibleTargetModules.remove(fFocusModule.getElementName());
ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(shell, new IJavaElement[] { jContainer }, possibleTargetModules, initial);
if (dialog.open() == Window.OK) {
+ try {
+ moduleAttribute = ensureModuleAttribute(moduleAttribute);
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ return false;
+ }
ModuleAddExpose expose= dialog.getExport(moduleAttribute);
if (expose != null) {
Object attribute= moduleAttribute.getValue();
@@ -354,8 +363,9 @@
}
private boolean internalRemove(List<Object> selectedElements) throws JavaModelException {
CPListElementAttribute moduleAttribute;
- if (fKind == ModuleKind.System) {
- moduleAttribute= ((CPListElement) fElem.getParentContainer()).findAttributeElement(CPListElement.MODULE);
+ Object parentContainer= fElem.getParentContainer();
+ if (parentContainer instanceof CPListElement) {
+ moduleAttribute= ((CPListElement) parentContainer).findAttributeElement(CPListElement.MODULE);
} else {
moduleAttribute= fElem.findAttributeElement(CPListElement.MODULE);
}
@@ -375,6 +385,9 @@
// need to merge details:
PatchModule patch= (PatchModule) node;
ModuleEncapsulationDetail.removePatchLocation(details, fFocusModule.getElementName(), patch.getPath());
+ if (getContextProject().equals(patch.fSource.getAncestor(IJavaElement.JAVA_PROJECT))) {
+ fDependenciesPage.unsetFocusModule(fElem);
+ }
patchUpdated= true;
} else {
ModuleEncapsulationDetail med= ((DetailNode<?>) node).convertToCP(moduleAttribute);
@@ -416,7 +429,7 @@
return false;
}
}
- private boolean internalAddReads(Shell shell) throws JavaModelException {
+ boolean internalAddReads(Shell shell) throws JavaModelException {
Object container= fElem.getParentContainer();
CPListElement element= (container instanceof CPListElement) ? (CPListElement) container : fElem;
CPListElementAttribute moduleAttribute= element.findAttributeElement(CPListElement.MODULE);
@@ -435,17 +448,18 @@
irrelevantModules= new ArrayList<>(irrelevantModules);
irrelevantModules.add(fFocusModule.getElementName());
- ModuleSelectionDialog dialog= ModuleSelectionDialog.forReads(shell, fElem.getJavaProject(), irrelevantModules);
+ IClasspathEntry jreEntry= fDependenciesPage.findSystemLibraryElement().getClasspathEntry();
+ ModuleSelectionDialog dialog= ModuleSelectionDialog.forReads(shell, fElem.getJavaProject(), jreEntry, irrelevantModules);
if (dialog.open() != 0) {
return false;
}
-
- if (moduleAttribute == null) {
- // initialize missing attribute for focus module (source folder)
- moduleAttribute= fElem.createAttributeElement(CPListElement.MODULE, new ModuleEncapsulationDetail[0], true);
+ List<IModuleDescription> result= dialog.getResult();
+ if (!handleUnavailableModulesIfNeeded(shell, result, fDependenciesPage)) {
+ return false;
}
- List<IModuleDescription> result= dialog.getResult();
+ moduleAttribute= ensureModuleAttribute(moduleAttribute);
+
ModuleEncapsulationDetail[] arrayValue= null;
int idx= 0;
Object attribute= moduleAttribute.getValue();
@@ -475,11 +489,7 @@
private boolean internalAddPatch(Shell shell, Map<String, String> patchMap) throws JavaModelException {
Object container= fElem.getParentContainer();
CPListElement element= (container instanceof CPListElement) ? (CPListElement) container : fElem;
- CPListElementAttribute moduleAttribute= element.findAttributeElement(CPListElement.MODULE);
- if (moduleAttribute == null) {
- throwNewJavaModelException("module attribute is unexpectecly missing for : "+fElem); //$NON-NLS-1$
- return false; // not reached
- }
+ CPListElementAttribute moduleAttribute= ensureModuleAttribute(element.findAttributeElement(CPListElement.MODULE));
if (!(moduleAttribute.getValue() instanceof ModuleEncapsulationDetail[])) {
throwNewJavaModelException("Value of module attribute has unexpected type: "+moduleAttribute.getValue()); //$NON-NLS-1$
return false;
@@ -531,6 +541,7 @@
ModuleEncapsulationDetail.addPatchLocations(detailList, fFocusModule.getElementName(), newPaths, moduleAttribute);
element.setAttribute(CPListElement.MODULE, detailList.toArray(new ModuleEncapsulationDetail[detailList.size()]));
fDependenciesPage.buildPatchMap();
+ fDependenciesPage.refreshModulesList();
return true;
}
@@ -550,6 +561,17 @@
otherAttribute.setValue(otherDetailList.toArray(new ModuleEncapsulationDetail[otherDetailList.size()]));
return true;
}
+
+ private CPListElementAttribute ensureModuleAttribute(CPListElementAttribute existing) throws JavaModelException {
+ if (existing != null) return existing;
+ if (fElem.getClasspathEntry().getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ // initialize missing attribute for focus module (source folder)
+ return fElem.createAttributeElement(CPListElement.MODULE, new ModuleEncapsulationDetail[0], true);
+ } else {
+ throwNewJavaModelException("module attribute is unexpectecly missing for : "+fElem); //$NON-NLS-1$
+ return null; // not reached
+ }
+ }
}
abstract static class DetailNode<D extends ModuleEncapsulationDetail> {
@@ -783,17 +805,61 @@
}
}
- public static void updateButtonEnablement(TreeListDialogField<?> list, boolean enableModify, boolean enableRemove) {
+ public static void updateButtonEnablement(TreeListDialogField<?> list, boolean enableModify, boolean enableRemove, boolean enableShow) {
list.enableButton(IDX_REMOVE, enableRemove);
list.enableButton(IDX_EXPOSE_PACKAGE, enableModify);
list.enableButton(IDX_READ_MODULE, enableModify);
list.enableButton(IDX_PATCH, enableModify);
+ list.enableButton(IDX_JPMS_OPTIONS, enableShow);
}
static void throwNewJavaModelException(String message) throws JavaModelException {
throw new JavaModelException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), message));
}
+ static boolean handleUnavailableModulesIfNeeded(Shell shell, List<IModuleDescription> result, ModuleDependenciesPage masterPage) {
+ List<IModuleDescription> unavailableSystemModules= new ArrayList<>();
+ Collection<String> allModules= masterPage.getAllModules();
+ for (IModuleDescription module : result) {
+ if (!allModules.contains(module.getElementName())) {
+ if (JavaModelAccess.isSystemModule(module)) {
+ unavailableSystemModules.add(module);
+ } else {
+ IPackageFragmentRoot pfr= (IPackageFragmentRoot) module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ boolean isLibrary= pfr != null && pfr.isArchive();
+ masterPage.offerSwitchToTab(shell,
+ NewWizardMessages.ModuleSelectionDialog_selectModule_title,
+ MessageFormat.format(NewWizardMessages.ModuleDependenciesAdapter_addReadsNotOnModulepath_error, module.getElementName()),
+ isLibrary);
+ return false; // the new add-reads is not yet handled
+ }
+ }
+ }
+ if (!unavailableSystemModules.isEmpty()) {
+ StringBuilder message= new StringBuilder();
+ message.append(NewWizardMessages.ModuleDependenciesAdapter_addSystemModules_question);
+ message.append(unavailableSystemModules.stream()
+ .map(IJavaElement::getElementName)
+ .sorted()
+ .collect(Collectors.joining("\n\t", "\t", ""))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ int answer= MessageDialog.open(MessageDialog.QUESTION, shell,
+ NewWizardMessages.ModuleDependenciesAdapter_addSystemModule_title, message.toString(), SWT.NONE,
+ NewWizardMessages.ModuleDependenciesAdapter_add_button, IDialogConstants.CANCEL_LABEL);
+ if (answer == 0) {
+ try {
+ masterPage.addToSystemModules(unavailableSystemModules);
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ MessageDialog.openError(shell, NewWizardMessages.ModuleDependenciesAdapter_configure_error, e.getMessage());
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
private final ModuleDependenciesPage fModuleDependenciesPage; // parent structure
private TreeListDialogField<Object> fDetailsList; // RHS widget managed by this class
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesList.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesList.java
index aeaf053..c85126b 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesList.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesList.java
@@ -188,9 +188,31 @@
return !fInitialNames.equals(fNames);
}
+ public void setFocusModule(String moduleName) {
+ fNamesComparator= new FocusAwareStringComparator(moduleName);
+ fKinds.put(fModule2Element.get(moduleName), ModuleKind.Focus);
+ }
+
+ public void unsetFocusModule(CPListElement elem) {
+ fNamesComparator= new FocusAwareStringComparator(""); //$NON-NLS-1$
+ // restore real kind:
+ Object topElem= elem.getParentContainer();
+ CPListElement topEntry= topElem instanceof CPListElement ? (CPListElement) topElem : elem;
+ ModuleKind kind= ModuleKind.Normal;
+ if (LibrariesWorkbookPage.isJREContainer(topEntry.getPath())) {
+ kind= ModuleKind.System;
+ } else {
+ IModuleDescription module= fModules.get(elem);
+ if (module != null && module.isAutoModule()) {
+ kind= ModuleKind.Automatic;
+ }
+ }
+ fKinds.put(elem, kind);
+ }
+
public void refresh() {
fNames.sort(fNamesComparator);
- fViewer.refresh();
+ fViewer.refresh(true, true);
}
public void setEnabled(boolean enable) {
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesPage.java
index 0cfc571..350b55c 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDependenciesPage.java
@@ -38,8 +38,11 @@
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.resources.IProject;
@@ -50,8 +53,6 @@
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
-
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
@@ -75,22 +76,14 @@
import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;
/*
- * TODO: ("+" must have, "-" later)
+ * TODO:
* LHS:
* - module kind "Upgrade" of a System Library (incl. icon decoration)
- * - better help on how to remove non-JRE modules (module-info, modulepath)
- * RHS:
- * - PatchModule:
- * - handle patch project w/o module-info (as soon as path-module is defined)
- * - treat the patched module as the current context module (pinned)
- * - prefer offering source folders of the context project for patch-module
* General:
* - distinguish test/main dependencies
* - special elements: ALL-UNNAMED, ALL-SYSTEM ...
* - Help pages and reference to it
* (add to ModuleSelectionDialog.configureShell(), ModuleDependenciesPage.getControl())
- * - Offer to switch to the corresponding tab when trying to remove a non-system module
- * (see error scenarii in #removeModules() and also field #fPageContainer).
*/
public class ModuleDependenciesPage extends BuildPathBasePage {
@@ -173,12 +166,10 @@
public final Map<String,String> fPatchMap= new HashMap<>();
private Control fSWTControl;
-// private final IWorkbenchPreferenceContainer fPageContainer; // for switching page (not yet used)
- public ModuleDependenciesPage(IStatusChangeListener context, CheckedListDialogField<CPListElement> classPathList, IWorkbenchPreferenceContainer pageContainer) {
+ public ModuleDependenciesPage(IStatusChangeListener context, CheckedListDialogField<CPListElement> classPathList) {
fClassPathList= classPathList;
fContext= context;
-// fPageContainer= pageContainer;
fSWTControl= null;
String[] buttonLabels= new String[] {
@@ -291,7 +282,7 @@
fAddSystemModuleButton.setEnabled(false);
fDetailsList.removeAllElements();
fDetailsList.refresh();
- ModuleDependenciesAdapter.updateButtonEnablement(fDetailsList, false, false);
+ ModuleDependenciesAdapter.updateButtonEnablement(fDetailsList, false, false, false);
return;
}
fModuleList.setEnabled(true);
@@ -396,9 +387,9 @@
}
}
}
+ buildPatchMap();
fModuleList.captureInitial();
fModuleList.refresh();
- buildPatchMap();
}
public Collection<String> getAllModules() {
@@ -415,6 +406,9 @@
ModulePatch patch= (ModulePatch) detail;
for (String path : patch.getPathArray()) {
fPatchMap.put(path, patch.fModule);
+ if (path.startsWith(fCurrJProject.getPath().toString())) {
+ fModuleList.setFocusModule(patch.fModule);
+ }
}
}
}
@@ -484,7 +478,7 @@
fDetailsList.addElement(configured);
fDetailsList.expandElement(configured, 1);
}
- ModuleDependenciesAdapter.updateButtonEnablement(fDetailsList, elements.size() == 1, !elements.isEmpty());
+ ModuleDependenciesAdapter.updateButtonEnablement(fDetailsList, elements.size() == 1, !elements.isEmpty(), true);
}
@Override
@@ -501,22 +495,40 @@
fDetailsList.setFocus();
}
+ public void unsetFocusModule(CPListElement elem) {
+ fModuleList.unsetFocusModule(elem);
+ fModuleList.refresh();
+ }
+
public void refreshModulesList() {
fModuleList.refresh();
}
void addSystemModules() {
- CPListElement cpListElement= findSystemLibraryElement();
- ModuleSelectionDialog dialog= ModuleSelectionDialog.forSystemModules(getShell(), fCurrJProject, cpListElement.getClasspathEntry(), fModuleList.fNames, this::computeForwardClosure);
- if (dialog.open() == IDialogConstants.OK_ID) {
- for (IModuleDescription addedModule : dialog.getResult()) {
- fModuleList.addModule(addedModule, getOrCreateModuleCPE(cpListElement, addedModule), ModuleKind.System);
+ try {
+ CPListElement cpListElement= findSystemLibraryElement();
+ ModuleSelectionDialog dialog= ModuleSelectionDialog.forSystemModules(getShell(), fCurrJProject, cpListElement.getClasspathEntry(), fModuleList.fNames, this::computeForwardClosure);
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ List<IModuleDescription> modulesToAdd= dialog.getResult();
+ addSystemModules(cpListElement, modulesToAdd);
}
- updateLimitModules(cpListElement.findAttributeElement(CPListElement.MODULE));
- fModuleList.refresh();
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
}
}
+ void addSystemModules(CPListElement cpListElement, List<IModuleDescription> modulesToAdd) {
+ for (IModuleDescription addedModule : modulesToAdd) {
+ fModuleList.addModule(addedModule, getOrCreateModuleCPE(cpListElement, addedModule), ModuleKind.System);
+ }
+ updateLimitModules(cpListElement.findAttributeElement(CPListElement.MODULE));
+ fModuleList.refresh();
+ }
+
+ public void addToSystemModules(List<IModuleDescription> modulesToAdd) throws JavaModelException {
+ addSystemModules(findSystemLibraryElement(), modulesToAdd);
+ }
+
CPListElement getOrCreateModuleCPE(CPListElement parentCPE, IModuleDescription module) {
CPListElement element= fModuleList.fModule2Element.get(module.getElementName());
if (element != null) {
@@ -524,18 +536,21 @@
}
try {
IClasspathEntry entry= fCurrJProject.getClasspathEntryFor(module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT).getPath());
+ if (entry == null) {
+ return null;
+ }
return CPListElement.create(parentCPE, entry, module, true, fCurrJProject);
} catch (JavaModelException e) {
JavaPlugin.log(e);
return null;
}
}
- private CPListElement findSystemLibraryElement() {
+ public CPListElement findSystemLibraryElement() throws JavaModelException {
for (CPListElement cpListElement : fClassPathList.getElements()) {
if (LibrariesWorkbookPage.isJREContainer(cpListElement.getPath()))
return cpListElement;
}
- return null;
+ throw new JavaModelException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), "Project "+fCurrJProject.getElementName()+" has no system library")); //$NON-NLS-1$//$NON-NLS-2$
}
void removeModules() {
@@ -550,9 +565,39 @@
}
IModuleDescription mod= selectedElement.getModule();
if (mod == null) {
- MessageDialog.openError(getShell(), NewWizardMessages.ModuleDependenciesPage_removeModule_dialog_title,
+ // offer to switch to the suitable Modulepath tab, but need to collect some info, first:
+ IClasspathEntry selectedEntry= selectedElement.getClasspathEntry();
+ String moduleName= selectedElement.getPath().lastSegment();
+ boolean isLibrary;
+ switch (selectedEntry.getEntryKind()) {
+ case IClasspathEntry.CPE_LIBRARY:
+ for (IPackageFragmentRoot packageRoot : fCurrJProject.findPackageFragmentRoots(selectedEntry)) {
+ IModuleDescription module= packageRoot.getModuleDescription();
+ if (module == null) {
+ try {
+ module= JavaCore.getAutomaticModuleDescription(packageRoot);
+ } catch (JavaModelException | IllegalArgumentException e) {
+ // ignore
+ }
+ }
+ if (module != null) {
+ moduleName= module.getElementName();
+ break;
+ }
+ }
+ //$FALL-THROUGH$
+ case IClasspathEntry.CPE_CONTAINER:
+ case IClasspathEntry.CPE_VARIABLE:
+ isLibrary= true;
+ break;
+ default:
+ isLibrary= false;
+ }
+ offerSwitchToTab(getShell(),
+ NewWizardMessages.ModuleDependenciesPage_removeModule_dialog_title,
MessageFormat.format(NewWizardMessages.ModuleDependenciesPage_removeModule_error_with_hint,
- selectedElement.getPath().lastSegment(), NewWizardMessages.ModuleDependenciesPage_removeSystemModule_error_hint));
+ moduleName, NewWizardMessages.ModuleDependenciesPage_removeSystemModule_error_hint),
+ isLibrary);
return;
}
String moduleName= mod.getElementName();
@@ -624,7 +669,9 @@
}
private boolean confirmRemoveModule(String message) {
- int answer= MessageDialog.open(MessageDialog.QUESTION, getShell(), NewWizardMessages.ModuleDependenciesPage_removeModule_dialog_title, message, SWT.NONE, NewWizardMessages.ModuleDependenciesPage_remove_button, NewWizardMessages.ModuleDependenciesPage_cancel_button);
+ int answer= MessageDialog.open(MessageDialog.QUESTION, getShell(),
+ NewWizardMessages.ModuleDependenciesPage_removeModule_dialog_title, message, SWT.NONE,
+ NewWizardMessages.ModuleDependenciesPage_remove_button, IDialogConstants.CANCEL_LABEL);
return answer == 0;
}
@@ -737,4 +784,42 @@
public void showJMPSOptionsDialog() {
new ShowJPMSOptionsDialog(getShell(), fClassPathList, allDefaultSystemModules(), this::closure, this::reduceNames).open();
}
+
+ public void offerSwitchToTab(Shell shell, String dialogTitle, String dialogMessage, boolean isLibrary) {
+ String tabButton= isLibrary ? NewWizardMessages.ModuleDependenciesAdapter_goToLibrariesTab_button
+ : NewWizardMessages.ModuleDependenciesAdapter_goToProjectsTab_button;
+ MessageDialog dialog= new MessageDialog(shell,
+ dialogTitle, null, dialogMessage, MessageDialog.QUESTION, 0,
+ tabButton, IDialogConstants.CANCEL_LABEL);
+ if (dialog.open() == 0) {
+ TabFolder tabFolder= (TabFolder) fSWTControl.getParent();
+ if (isLibrary) {
+ showLibrariesPage(tabFolder);
+ } else {
+ showProjectsPage(tabFolder);
+ }
+ }
+ }
+
+ void showLibrariesPage(TabFolder tabFolder) {
+ for (TabItem tabItem : tabFolder.getItems()) {
+ if (tabItem.getData() instanceof LibrariesWorkbookPage) {
+ tabFolder.setSelection(tabItem);
+ LibrariesWorkbookPage page= (LibrariesWorkbookPage) tabItem.getData();
+ page.selectRootNode(true);
+ return;
+ }
+ }
+ }
+
+ void showProjectsPage(TabFolder tabFolder) {
+ for (TabItem tabItem : tabFolder.getItems()) {
+ if (tabItem.getData() instanceof ProjectsWorkbookPage) {
+ tabFolder.setSelection(tabItem);
+ ProjectsWorkbookPage page= (ProjectsWorkbookPage) tabItem.getData();
+ page.selectRootNode(true);
+ return;
+ }
+ }
+ }
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java
index 3164564..d750add 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java
@@ -23,8 +23,11 @@
import java.util.stream.Collectors;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jdt.core.IClasspathAttribute;
@@ -207,6 +210,79 @@
public String getAttributeName() {
return IClasspathAttribute.PATCH_MODULE;
}
+
+ public String toAbsolutePathsString(IJavaProject focusProject) {
+ String[] paths= fPaths.split(File.pathSeparator);
+ String[] absPaths= new String[paths.length];
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ for (int i= 0; i < paths.length; i++) {
+ IResource resource= root.findMember(new Path(paths[i]));
+ try {
+ absPaths[i]= toAbsolutePath(resource, focusProject, root);
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ if (absPaths[i] == null) {
+ absPaths[i]= paths[i];
+ }
+ }
+ String allPaths= String.join(File.pathSeparator, absPaths);
+ return fModule + '=' + allPaths;
+ }
+
+ private String toAbsolutePath(IResource resource, IJavaProject focusProject, IWorkspaceRoot root) throws JavaModelException {
+ if (resource instanceof IProject) {
+ if (resource.equals(focusProject.getProject())) {
+ // focus project: collect all source locations (pre-joined into one string):
+ StringBuilder allSources= new StringBuilder();
+ for (IClasspathEntry classpathEntry : focusProject.getRawClasspath()) {
+ if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ if (allSources.length() > 0) {
+ allSources.append(File.pathSeparator);
+ }
+ allSources.append(absPath(root, classpathEntry.getPath()));
+ }
+ }
+ return allSources.toString();
+ } else {
+ // other projects: use the default output locations:
+ return absPath(root, JavaCore.create((IProject) resource).getOutputLocation());
+ }
+ } else if (resource != null) {
+ if (isSourceFolderOf(resource, focusProject)) {
+ // within current project use source path:
+ return resource.getLocation().toString();
+ } else {
+ IJavaProject otherJProj= JavaCore.create(resource.getProject());
+ if (otherJProj.exists()) {
+ IClasspathEntry cpEntry= otherJProj.getClasspathEntryFor(resource.getFullPath());
+ if (cpEntry != null && cpEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ // source of other project -> map to its output location:
+ IPath outputLocation= cpEntry.getOutputLocation();
+ if (outputLocation == null) {
+ outputLocation= otherJProj.getOutputLocation();
+ }
+ return absPath(root, outputLocation);
+ }
+ }
+ // non-source location as-is:
+ return resource.getLocation().toString();
+ }
+ }
+ return null;
+ }
+
+ private String absPath(IWorkspaceRoot root, IPath path) {
+ return root.findMember(path).getLocation().toString();
+ }
+
+ private boolean isSourceFolderOf(IResource resource, IJavaProject javaProject) throws JavaModelException {
+ IPackageFragmentRoot root= javaProject.findPackageFragmentRoot(resource.getFullPath());
+ if (root != null) {
+ return root.getKind() == IPackageFragmentRoot.K_SOURCE;
+ }
+ return false;
+ }
}
/** Shared implementation for ModuleAddExports & ModuleAddOpens (same structure). */
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModulePatchSourceSelectionDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModulePatchSourceSelectionDialog.java
index 97ea38f..b68cde9 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModulePatchSourceSelectionDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModulePatchSourceSelectionDialog.java
@@ -98,7 +98,7 @@
if (e1.equals(fContextProject)) {
return -1;
}
- if (e1.equals(fContextProject)) {
+ if (e2.equals(fContextProject)) {
return 1;
}
return super.compare(viewer, e1, e2);
@@ -151,7 +151,7 @@
continue;
}
try {
- if (project.hasNature(JavaCore.NATURE_ID)) {
+ if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject jProj= JavaCore.create(project);
if (jProj.getModuleDescription() == null) {
fProjects.add(jProj);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleSelectionDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleSelectionDialog.java
index b5f5297..0044493 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleSelectionDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleSelectionDialog.java
@@ -58,7 +58,9 @@
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.provisional.JavaModelAccess;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
@@ -66,6 +68,7 @@
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.search.JavaSearchScopeFactory;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleDependenciesList.ModuleKind;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleDependenciesList.ModulesLabelProvider;
@@ -83,10 +86,7 @@
private SelectionButtonDialogField fSelectAllCheckbox;
boolean fInSetSelection= false; // to avoid re-entrance -> StackOverflow
-
- // input data:
- private IJavaProject fJavaProject;
- private IClasspathEntry fJREEntry;
+ boolean fWaitingForSearch= false;
// internal storage and a client-provided function:
private Set<String> fAllIncluded; // transitive closure over modules already shown
@@ -108,43 +108,45 @@
* @return the configured dialog
*/
public static ModuleSelectionDialog forSystemModules(Shell shell, IJavaProject javaProject, IClasspathEntry jreEntry, List<String> shownModules, Function<List<String>, Set<String>> closureComputation) {
- return new ModuleSelectionDialog(shell, javaProject, jreEntry, shownModules, closureComputation,
+ return new ModuleSelectionDialog(shell, javaProject, jreEntry, false, shownModules, closureComputation,
NewWizardMessages.ModuleSelectionDialog_addSystemModules_title, NewWizardMessages.ModuleSelectionDialog_addSystemModules_message);
}
/**
* Let the user select a module from all modules found in the workspace, except those in {@code irrelevantModules}.
* @param shell for showing the dialog
* @param javaProject the java project whose build path is being configured
+ * @param jreEntry a classpath entry representing the JRE system library
* @param irrelevantModules list of modules not relevant for selection
* @return the configured dialog
*/
- public static ModuleSelectionDialog forReads(Shell shell, IJavaProject javaProject, List<String> irrelevantModules) {
- return new ModuleSelectionDialog(shell, javaProject, null, irrelevantModules, HashSet::new,
+ public static ModuleSelectionDialog forReads(Shell shell, IJavaProject javaProject, IClasspathEntry jreEntry, List<String> irrelevantModules) {
+ return new ModuleSelectionDialog(shell, javaProject, jreEntry, true, irrelevantModules, HashSet::new,
NewWizardMessages.ModuleSelectionDialog_selectModule_title, NewWizardMessages.ModuleSelectionDialog_selectReadModule_message);
}
- private ModuleSelectionDialog(Shell shell, IJavaProject javaProject, IClasspathEntry jreEntry, List<String> shownModules,
- Function<List<String>, Set<String>> closureComputation, String title, String message) {
+ private ModuleSelectionDialog(Shell shell, IJavaProject javaProject, IClasspathEntry jreEntry, boolean searchWorkspace,
+ List<String> shownModules, Function<List<String>, Set<String>> closureComputation, String title, String message) {
super(shell);
fTitle= title;
fMessage= message;
- fJavaProject= javaProject;
- fJREEntry= jreEntry;
fAllIncluded= closureComputation.apply(shownModules);
fClosureComputation= closureComputation;
- if (jreEntry != null) { // searching only modules from this JRE entry (quick)
+ if (jreEntry != null) { // find system modules from this JRE entry (quick)
Set<String> result= new HashSet<>();
- for (IPackageFragmentRoot root : fJavaProject.findUnfilteredPackageFragmentRoots(fJREEntry)) {
+ for (IPackageFragmentRoot root : javaProject.findUnfilteredPackageFragmentRoots(jreEntry)) {
checkAddModule(result, root.getModuleDescription());
}
List<String> list= new ArrayList<>(result);
list.sort(String::compareTo);
fAvailableModules= list;
- } else { // searching all modules in the workspace (slow)
+ }
+ if (searchWorkspace) { // searching all modules in the workspace (slow)
+ fWaitingForSearch= true;
new Job(NewWizardMessages.ModuleSelectionDialog_searchModules_job) {
@Override
public IStatus run(IProgressMonitor monitor) {
try {
- fAvailableModules= searchAvailableModules(monitor);
+ fAvailableModules.addAll(searchAvailableModules(monitor));
+ fAvailableModules.sort(String::compareTo);
if (getReturnCode() == Window.CANCEL) {
return Status.CANCEL_STATUS;
}
@@ -172,17 +174,21 @@
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Object element= match.getElement();
if (element instanceof IModuleDescription) {
- checkAddModule(result, (IModuleDescription) element);
+ IModuleDescription module= (IModuleDescription) element;
+ if (!JavaModelAccess.isSystemModule(module))
+ checkAddModule(result, module);
}
}
};
SearchParticipant[] participants= new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() };
- new SearchEngine().search(pattern, participants, SearchEngine.createWorkspaceScope(), requestor, monitor);
+ IJavaSearchScope scope= JavaSearchScopeFactory.getInstance().createWorkspaceScope(false); // skip JRE modules, which are found directly via the jreEntry
+ new SearchEngine().search(pattern, participants, scope, requestor, monitor);
if (getReturnCode() == Window.CANCEL) { // should cancelPressed() actively abort the search?
return Collections.emptyList();
}
// also search for automatic modules:
for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ if (!project.isOpen()) continue;
IJavaProject jPrj= JavaCore.create(project);
if (jPrj.getModuleDescription() == null) {
checkAddModule(result, JavaCore.getAutomaticModuleDescription(jPrj));
@@ -195,9 +201,7 @@
}
}
}
- List<String> list= new ArrayList<>(result);
- list.sort(String::compareTo);
- return list;
+ return new ArrayList<>(result);
}
boolean isJREChild(IJavaProject jPrj, IPackageFragmentRoot root) {
@@ -275,15 +279,17 @@
gd.heightHint= converter.convertHeightInCharsToPixels(20);
tableViewer.getControl().setLayoutData(gd);
- if (fAvailableModules == null) {
+ if (fWaitingForSearch) {
message.setText(NewWizardMessages.ModuleSelectionDialog_searchModules_temp_message);
fFlipMessage= () -> {
message.setText(fMessage);
};
} else {
- tableViewer.setInput(fAvailableModules);
message.setText(fMessage);
}
+ if (fAvailableModules != null) {
+ tableViewer.setInput(fAvailableModules);
+ }
fViewer= tableViewer;
fSelectAllCheckbox= new SelectionButtonDialogField(SWT.CHECK);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
index 2facc8c..acdb4d8 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -785,4 +785,8 @@
public void setFocus() {
fProjectsList.setFocus();
}
+
+ public void selectRootNode(boolean modulePath) {
+ selectRootNode(fProjectsList, modulePath);
+ }
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ShowJPMSOptionsDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ShowJPMSOptionsDialog.java
index a94faad..00faf2f 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ShowJPMSOptionsDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ShowJPMSOptionsDialog.java
@@ -30,6 +30,7 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
@@ -46,6 +47,7 @@
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModulePatch;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
/**
@@ -102,20 +104,25 @@
protected Control createDialogArea(Composite parent) {
Composite comp= (Composite) super.createDialogArea(parent);
Font font= parent.getFont();
+ int widthHint= convertWidthInCharsToPixels(60);
+
+ Label message= new Label(comp, SWT.LEFT + SWT.WRAP);
+ message.setText(NewWizardMessages.ShowJPMSOptionsDialog_explanation_label);
+ GridData gdLabel= new GridData(SWT.FILL, SWT.NONE, true, false);
+ gdLabel.widthHint= widthHint;
+ message.setLayoutData(gdLabel);
Group group= new Group(comp, SWT.NONE);
GridLayout topLayout= new GridLayout();
group.setLayout(topLayout);
GridData gd= new GridData(GridData.FILL_BOTH);
gd.heightHint= convertHeightInCharsToPixels(15);
- gd.widthHint= convertWidthInCharsToPixels(50);
+ gd.widthHint= widthHint;
group.setLayoutData(gd);
group.setFont(font);
fJPMSModuleOptionsText= new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
gd= new GridData(GridData.FILL_BOTH);
- gd.heightHint= convertHeightInCharsToPixels(10);
- gd.widthHint= convertWidthInCharsToPixels(60);
fJPMSModuleOptionsText.setLayoutData(gd);
String command= getOptions();
@@ -158,9 +165,10 @@
case IClasspathAttribute.ADD_EXPORTS:
case IClasspathAttribute.ADD_OPENS:
case IClasspathAttribute.ADD_READS:
- for (String value : detail.toString().split(COMMA)) {
- buf.append(OPTION_START).append(optName).append(BLANK).append(value).append(BLANK);
- }
+ buf.append(OPTION_START).append(optName).append(BLANK).append(detail.toString()).append(BLANK);
+ break;
+ case IClasspathAttribute.PATCH_MODULE:
+ buf.append(OPTION_START).append(optName).append(BLANK).append(((ModulePatch) detail).toAbsolutePathsString(cpElement.getJavaProject())).append(BLANK);
break;
case IClasspathAttribute.LIMIT_MODULES:
addLimitModules(buf, systemLibrary.getJavaProject(), detail.toString());