Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2017-09-03 18:50:39 +0000
committerStephan Herrmann2017-09-16 12:16:02 +0000
commit8362220c2bf1e277c0bf682fdd1d0d3624bb63ec (patch)
tree179300a98ed6292d57ea0a157cb945fe72470188
parentef015e1292f9fe5a9d40590896d5c2c8a0c88b02 (diff)
downloadeclipse.jdt.ui-8362220c2bf1e277c0bf682fdd1d0d3624bb63ec.tar.gz
eclipse.jdt.ui-8362220c2bf1e277c0bf682fdd1d0d3624bb63ec.tar.xz
eclipse.jdt.ui-8362220c2bf1e277c0bf682fdd1d0d3624bb63ec.zip
Bug 521666: [9] Add --add-reads,--patch-module and --limit-modulesY20170916-1000
-rw-r--r--org.eclipse.jdt.ui/icons/full/etool16/move_up.pngbin0 -> 315 bytes
-rw-r--r--org.eclipse.jdt.ui/icons/full/etool16/move_up@2x.pngbin0 -> 538 bytes
-rw-r--r--org.eclipse.jdt.ui/icons/full/obj16/export_package.pngbin639 -> 0 bytes
-rw-r--r--org.eclipse.jdt.ui/plugin.xml4
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPluginImages.java5
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java4
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java48
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties51
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/BuildPathBasePage.java36
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java91
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListLabelProvider.java40
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java16
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExport.java135
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsAttributeConfiguration.java78
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsBlock.java22
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsDialog.java10
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsBlock.java249
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsDialog.java128
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDialog.java833
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java228
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java16
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/ISharedImages.java12
-rw-r--r--org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/BuildPathDialogAccess.java22
23 files changed, 1534 insertions, 494 deletions
diff --git a/org.eclipse.jdt.ui/icons/full/etool16/move_up.png b/org.eclipse.jdt.ui/icons/full/etool16/move_up.png
new file mode 100644
index 0000000000..7eaaff9798
--- /dev/null
+++ b/org.eclipse.jdt.ui/icons/full/etool16/move_up.png
Binary files differ
diff --git a/org.eclipse.jdt.ui/icons/full/etool16/move_up@2x.png b/org.eclipse.jdt.ui/icons/full/etool16/move_up@2x.png
new file mode 100644
index 0000000000..0b95e38b51
--- /dev/null
+++ b/org.eclipse.jdt.ui/icons/full/etool16/move_up@2x.png
Binary files differ
diff --git a/org.eclipse.jdt.ui/icons/full/obj16/export_package.png b/org.eclipse.jdt.ui/icons/full/obj16/export_package.png
deleted file mode 100644
index f45bdbd75c..0000000000
--- a/org.eclipse.jdt.ui/icons/full/obj16/export_package.png
+++ /dev/null
Binary files differ
diff --git a/org.eclipse.jdt.ui/plugin.xml b/org.eclipse.jdt.ui/plugin.xml
index 468f4d8aba..491001473e 100644
--- a/org.eclipse.jdt.ui/plugin.xml
+++ b/org.eclipse.jdt.ui/plugin.xml
@@ -185,10 +185,6 @@
attributeName="module"
class="org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleAttributeConfiguration">
</classpathAttributeConfiguration>
- <classpathAttributeConfiguration
- attributeName="add-exports"
- class="org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleAddExportsAttributeConfiguration">
- </classpathAttributeConfiguration>
</extension>
<!-- Not used to create markers but to allow registering a -->
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPluginImages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPluginImages.java
index df2cfe27cf..923821d651 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPluginImages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaPluginImages.java
@@ -148,7 +148,6 @@ public class JavaPluginImages {
public static final String IMG_OBJS_JAVADOCTAG= NAME_PREFIX + "jdoc_tag_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_EXTERNAL_ANNOTATIONS = NAME_PREFIX + "external_annotation_location_attrib.gif"; //$NON-NLS-1$
- public static final String IMG_OBJS_ADD_EXPORTS = NAME_PREFIX + "export_package.png"; //$NON-NLS-1$
public static final String IMG_OBJS_HTMLTAG= NAME_PREFIX + "html_tag_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_TEMPLATE= NAME_PREFIX + "template_obj.gif"; //$NON-NLS-1$
@@ -215,6 +214,8 @@ public class JavaPluginImages {
public static final ImageDescriptor DESC_MENU_SHIFT_LEFT= createUnManaged(T_ETOOL, "shift_l_edit.png"); //$NON-NLS-1$
public static final ImageDescriptor DESC_CLASSPATH_ROOT= createUnManaged(T_ETOOL, "classpath_obj.png"); //$NON-NLS-1$
+ public static final ImageDescriptor DESC_BUTTON_MOVE_UP= createUnManaged(T_ETOOL, "move_up.png"); //$NON-NLS-1$
+
public static final ImageDescriptor DESC_OBJS_GHOST= createManagedFromKey(T_OBJ, IMG_OBJS_GHOST);
public static final ImageDescriptor DESC_OBJS_PACKDECL= createManagedFromKey(T_OBJ, IMG_OBJS_PACKDECL);
public static final ImageDescriptor DESC_OBJS_IMPDECL= createManagedFromKey(T_OBJ, IMG_OBJS_IMPDECL);
@@ -312,8 +313,6 @@ public class JavaPluginImages {
public static final ImageDescriptor DESC_OBJS_EXTERNAL_ANNOTATION_LOCATION_ATTRIB= createManagedFromKey(T_OBJ, IMG_OBJS_EXTERNAL_ANNOTATIONS);
- public static final ImageDescriptor DESC_OBJS_ADD_EXPORTS_ATTRIB= createManagedFromKey(T_OBJ, IMG_OBJS_ADD_EXPORTS);
-
public static final ImageDescriptor DESC_OBJS_ACCESSRULES_ATTRIB= createManagedFromKey(T_OBJ, IMG_OBJS_ACCESSRULES_ATTRIB);
public static final ImageDescriptor DESC_OBJS_NATIVE_LIB_PATH_ATTRIB= createUnManaged(T_OBJ, "native_lib_path_attrib.png"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java
index a5a473237c..d719f1e86e 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/UserLibraryPreferencePage.java
@@ -126,7 +126,7 @@ import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPUserLibraryElement;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathAttributeConfigurationDescriptors;
-import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleAddExport;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceAttachmentBlock;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
@@ -1519,7 +1519,7 @@ public class UserLibraryPreferencePage extends PreferencePage implements IWorkbe
return (IAccessRule[]) attribute.getValue();
}
if (CPListElement.MODULE.equals(attribute.getKey())) {
- return (ModuleAddExport[]) attribute.getValue();
+ return (ModuleEncapsulationDetail[]) attribute.getValue();
}
}
return EMPTY;
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 46326a4868..76cb370797 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
@@ -451,27 +451,58 @@ public final class NewWizardMessages extends NLS {
public static String ModuleDialog_container_description;
public static String ModuleDialog_project_description;
public static String ModuleDialog_defines_modules_label;
- public static String ModuleDialog_duplicatePackage_error;
+ public static String ModuleDialog_errorOnContentsTab_error;
+ public static String ModuleDialog_errorOnDetailsTab_error;
+
+ public static String ModuleDialog_contents_tab;
+ public static String ModuleDialog_availableModules_list;
+ public static String ModuleDialog_availableModules_tooltip;
+ public static String ModuleDialog_explicitlyIncludedModules_list;
+ public static String ModuleDialog_explicitlyIncludedModules_tooltip;
+ public static String ModuleDialog_implicitelyIncludedModules_list;
+ public static String ModuleDialog_implicitlyIncludedModule_tooltip;
+ public static String ModuleDialog_addToIncluded_tooltip;
+ public static String ModuleDialog_removeFromIncluded_tooltip;
+ public static String ModuleDialog_addToExplicitlyIncluded_tooltip;
+ public static String ModuleDialog_cannotLimitSingle_error;
+
+ public static String ModuleDialog_details_tab;
+ public static String ModuleDialog_patches_module_label;
+ public static String ModuleDialog_patched_module_label;
+ public static String ModuleDialog_patchedModuleExcluded_error;
public static String ModuleDialog_source_module_header;
public static String ModuleDialog_package_header;
- public static String ModuleDialog_target_modules_header;
+ public static String ModuleDialog_target_module_header;
public static String ModuleDialog_exports_label;
- public static String ModuleDialog_exports_add;
- public static String ModuleDialog_exports_edit;
- public static String ModuleDialog_exports_remove;
+ public static String ModuleDialog_exportSourceModuleExcluded_error;
+ public static String ModuleDialog_reads_label;
+ public static String ModuleDialog_readsSourceModuleExcluded_error;
+ public static String ModuleDialog_detail_add;
+ public static String ModuleDialog_detail_edit;
+ public static String ModuleDialog_detail_remove;
+ public static String ModuleDialog_duplicatePackage_error;
+ public static String ModuleDialog_duplicateReads_error;
+ public static String ModuleDialog_missingPatch_error;
+ public static String ModuleDialog_wrongPatch_error;
+ public static String ModuleDialog_mustIncludeModule_error;
public static String ModuleAddExportsBlock_packageEmpty_error;
public static String ModuleAddExportsBlock_sourceModuleEmpty_error;
public static String ModuleAddExportsBlock_wrongPackage_error;
public static String ModuleAddExportsBlock_wrongSourceModule_error;
- public static String AddExportsDialog_notPersisted_warning;
+ public static String AddModuleDetailsDialog_notPersisted_warning;
public static String AddExportsDialog_title;
public static String AddExportsBlock_message;
public static String AddExportsBlock_sourceModule_label;
public static String AddExportsBlock_package_label;
public static String AddExportsBlock_targetModules_label;
+
+ public static String AddReadsDialog_title;
+ public static String AddReadsBlock_message;
+ public static String AddReadsBlock_sourceModule_label;
+ public static String AddReadsBlock_targetModule_label;
//
public static String EditVariableEntryDialog_title;
@@ -649,10 +680,15 @@ public final class NewWizardMessages extends NLS {
public static String CPListLabelProvider_module_no;
public static String CPListLabelProvider_modular_modifiesEncapsulation_label;
public static String CPListLabelProvider_modular_label;
+ public static String CPListLabelProvider_modular_limitsAndModifies_label;
+ public static String CPListLabelProvider_modular_limitsModules_label;
public static String CPListLabelProvider_not_modular_label;
public static String CPListLabelProvider_add_exports_name_label;
+ public static String CPListLabelProvider_patch_module_full_label;
public static String CPListLabelProvider_add_exports_full_label;
+ public static String CPListLabelProvider_add_reads_full_label;
+ public static String CPListLabelProvider_limitModules_full_label;
public static String NewSourceFolderDialog_useproject_button;
public static String NewSourceFolderDialog_usefolder_button;
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 ef3957f0eb..50c34a829f 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
@@ -488,14 +488,40 @@ ModuleDialog_description=Module related details for ''{0}''.
ModuleDialog_container_description=Module related details for the library ''{0}''.
ModuleDialog_project_description=Module related details for the project ''{0}''.
ModuleDialog_defines_modules_label=&Defines one or more modules
-ModuleDialog_duplicatePackage_error=Duplicate package {0}
-ModuleDialog_exports_label=Added exports:
-ModuleDialog_target_modules_header=Target module
+ModuleDialog_errorOnContentsTab_error=Error exists on Contents tab
+ModuleDialog_errorOnDetailsTab_error=Error exists on Details tab
+
+ModuleDialog_contents_tab=Contents
+ModuleDialog_availableModules_list=Available modules:
+ModuleDialog_availableModules_tooltip=Modules that are available in the current classpath entry, but not included in the module path
+ModuleDialog_explicitlyIncludedModules_list=Explicitly included modules:
+ModuleDialog_explicitlyIncludedModules_tooltip=Modules that are explicitly included in the module path
+ModuleDialog_implicitelyIncludedModules_list=Implicitly included modules:
+ModuleDialog_implicitlyIncludedModule_tooltip=Modules that are implicitly included in the module path, because they are required by explicitly included modules
+ModuleDialog_addToIncluded_tooltip=Add selected to included modules
+ModuleDialog_removeFromIncluded_tooltip=Remove selected from included modules
+ModuleDialog_addToExplicitlyIncluded_tooltip=Add selected to explicitly included modules
+ModuleDialog_cannotLimitSingle_error=Cannot limit a single-module entry
+
+ModuleDialog_details_tab=Details
+ModuleDialog_patches_module_label=Patches an existing module
+ModuleDialog_patched_module_label=Patched module:
+ModuleDialog_patchedModuleExcluded_error=Patched module {0} is excluded on the Contents tab
+ModuleDialog_exports_label=Added &exports:
+ModuleDialog_exportSourceModuleExcluded_error=Cannot export package {0}, because declaring module {1} is excluded
+ModuleDialog_reads_label=Added &read modules:
+ModuleDialog_readsSourceModuleExcluded_error=Cannot add 'reads' to module {0}, which is excluded on the Contents tab
+ModuleDialog_target_module_header=Target module
ModuleDialog_package_header=Package
ModuleDialog_source_module_header=Source module
-ModuleDialog_exports_add=&Add...
-ModuleDialog_exports_edit=Edi&t...
-ModuleDialog_exports_remove=Rem&ove
+ModuleDialog_detail_add=Add...
+ModuleDialog_detail_edit=Edit...
+ModuleDialog_detail_remove=Remove
+ModuleDialog_duplicatePackage_error=Duplicate package {0}
+ModuleDialog_duplicateReads_error=Duplicate reads ''{0}''
+ModuleDialog_missingPatch_error=Must specify the module to be patched
+ModuleDialog_wrongPatch_error=Module {0} is not provided by this build path entry
+ModuleDialog_mustIncludeModule_error=Must include at least one module
ModuleAddExportsBlock_packageEmpty_error=Package is empty
ModuleAddExportsBlock_sourceModuleEmpty_error=Source module is empty
@@ -503,13 +529,19 @@ ModuleAddExportsBlock_wrongPackage_error=Package {0} is not provided by module {
ModuleAddExportsBlock_wrongSourceModule_error=Module {0} is not provided by this build path entry
# ------- ModuleAddExportsDialog ---------
-AddExportsDialog_notPersisted_warning=Build path entry has not yet been persisted; content assist is not available.
+AddModuleDetailsDialog_notPersisted_warning=Build path entry has not yet been persisted; content assist is not available.
AddExportsDialog_title=Add-exports configuration
AddExportsBlock_message=Enter the details of the export to add
AddExportsBlock_sourceModule_label=Source module
AddExportsBlock_package_label=Package
AddExportsBlock_targetModules_label=Target module
+# ------- ModuleAddReadsDialog ---------
+AddReadsDialog_title=Add-reads configuration
+AddReadsBlock_message=Enter the details of the reads edge to add
+AddReadsBlock_sourceModule_label=Source module
+AddReadsBlock_targetModule_label=Target module
+
# ------- EditVariableEntryDialog -------
EditVariableEntryDialog_title=Edit Variable Entry
@@ -746,10 +778,15 @@ CPListLabelProvider_module_yes=Yes
CPListLabelProvider_module_no=No
CPListLabelProvider_modular_modifiesEncapsulation_label=Is modular (modifies encapsulation)
CPListLabelProvider_modular_label=Is modular
+CPListLabelProvider_modular_limitsAndModifies_label=Is modular (limits modules and modifies encapsulation)
+CPListLabelProvider_modular_limitsModules_label=Is modular (limits modules)
CPListLabelProvider_not_modular_label=Is not modular
CPListLabelProvider_add_exports_name_label=add-exports
+CPListLabelProvider_patch_module_full_label=Patch-module: {0}
CPListLabelProvider_add_exports_full_label=Add-exports: {0}
+CPListLabelProvider_add_reads_full_label=Add-reads: {0}
+CPListLabelProvider_limitModules_full_label=Limit-modules: {0}
CPListLabelProvider_ignore_optional_problems_label=Ignore optional compile problems: {0}
CPListLabelProvider_ignore_optional_problems_yes=Yes
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 e2cc6b1839..5cd1228be1 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
@@ -75,10 +75,10 @@ public abstract class BuildPathBasePage {
return false;
}
- protected boolean showAddExportDialog(Shell shell, CPListElementAttribute elem) {
+ protected boolean showModuleDialog(Shell shell, CPListElementAttribute elem) {
CPListElement selElement= elem.getParent();
// the element targeted by the CP entry will be the source module from which packages are exported:
- IJavaElement[] selectedJavaElements= ModuleAddExport.getTargetJavaElements(selElement.getJavaProject(), selElement.getPath());
+ IJavaElement[] selectedJavaElements= ModuleEncapsulationDetail.getTargetJavaElements(selElement.getJavaProject(), selElement.getPath());
if (selectedJavaElements == null) {
MessageDialog dialog= new MessageDialog(shell, NewWizardMessages.BuildPathBasePage_notAddedQuestion_title, null,
Messages.format(NewWizardMessages.BuildPathBasePage_notAddedQuestion_description, selElement.getPath().toString()),
@@ -110,8 +110,8 @@ public abstract class BuildPathBasePage {
ModuleDialog dialog= new ModuleDialog(shell, selElement, selectedJavaElements);
int res= dialog.open();
if (res == Window.OK) {
- ModuleAddExport[] newExports= dialog.getAddExports();
- elem.setValue(newExports);
+ ModuleEncapsulationDetail[] newDetails= dialog.getAllDetails();
+ elem.setValue(newDetails);
return true;
}
return false;
@@ -133,7 +133,7 @@ public abstract class BuildPathBasePage {
}
};
PlatformUI.getWorkbench().getProgressService().run(true, true, new WorkbenchRunnableAdapter(runnable));
- selectedJavaElements= ModuleAddExport.getTargetJavaElements(element.getJavaProject(), element.getPath());
+ selectedJavaElements= ModuleEncapsulationDetail.getTargetJavaElements(element.getJavaProject(), element.getPath());
return selectedJavaElements;
}
@@ -149,22 +149,22 @@ public abstract class BuildPathBasePage {
return false;
}
- protected void removeAddExport(ModuleAddExport export) {
- CPListElementAttribute parent= export.getParent();
+ protected void removeEncapsulationDetail(ModuleEncapsulationDetail detail) {
+ CPListElementAttribute parent= detail.getParent();
if (parent != null) {
Object value= parent.getValue();
- if (value instanceof ModuleAddExport[]) {
- ModuleAddExport[] existingExports= (ModuleAddExport[]) value;
+ if (value instanceof ModuleEncapsulationDetail[]) {
+ ModuleEncapsulationDetail[] existingDetails= (ModuleEncapsulationDetail[]) value;
int count= 0;
- for (int j= 0; j < existingExports.length; j++) {
- ModuleAddExport anExport= existingExports[j];
- if (anExport != export)
- existingExports[count++]= anExport;
+ for (int j= 0; j < existingDetails.length; j++) {
+ ModuleEncapsulationDetail aDetail= existingDetails[j];
+ if (aDetail != detail)
+ existingDetails[count++]= aDetail;
}
- if (count < existingExports.length) {
- ModuleAddExport[] newExports= new ModuleAddExport[count];
- System.arraycopy(existingExports, 0, newExports, 0, count);
- parent.setValue(newExports);
+ if (count < existingDetails.length) {
+ ModuleEncapsulationDetail[] newDetails= new ModuleEncapsulationDetail[count];
+ System.arraycopy(existingDetails, 0, newDetails, 0, count);
+ parent.setValue(newDetails);
parent.getParent().attributeChanged(CPListElement.MODULE);
}
}
@@ -292,7 +292,7 @@ public abstract class BuildPathBasePage {
} else if (element instanceof CPListElementAttribute) {
CPListElementAttribute attribute= (CPListElementAttribute) element;
if (CPListElement.MODULE.equals(attribute.getKey())) {
- return (ModuleAddExport[]) attribute.getValue();
+ return (ModuleEncapsulationDetail[]) attribute.getValue();
}
}
return EMPTY_ARR;
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 2ffe715d98..64123e36d5 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
@@ -18,8 +18,10 @@ package org.eclipse.jdt.internal.ui.wizards.buildpaths;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.stream.Stream;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
@@ -42,7 +44,12 @@ import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.LimitModules;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModulePatch;
import org.eclipse.jdt.launching.JavaRuntime;
@@ -138,7 +145,7 @@ public class CPListElement {
createAttributeElement(SOURCEATTACHMENT, null, true);
createAttributeElement(JAVADOC, null, false);
createAttributeElement(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, null, false);
- createAttributeElement(MODULE, (module != null ? new ModuleAddExport[0] : null), true);
+ createAttributeElement(MODULE, (module != null ? new ModuleEncapsulationDetail[0] : null), true);
createAttributeElement(SOURCE_ATTACHMENT_ENCODING, null, false);
createAttributeElement(NATIVE_LIB_PATH, null, false);
createAttributeElement(ACCESSRULES, new IAccessRule[0], true);
@@ -163,7 +170,7 @@ public class CPListElement {
int beforeModules= fChildren.size();
boolean modulesAdded= addModuleNodes(entry, entries[0]);
if (modulesAdded) {
- fChildren.add(beforeModules, new CPListElementAttribute(this, MODULE, new ModuleAddExport[0], true));
+ fChildren.add(beforeModules, new CPListElementAttribute(this, MODULE, new ModuleEncapsulationDetail[0], true));
return;
}
}
@@ -208,6 +215,14 @@ public class CPListElement {
return modulesAdded;
}
+ private boolean hasLimitModules(IClasspathEntry entry) {
+ for (IClasspathAttribute attribute : entry.getExtraAttributes()) {
+ if (IClasspathAttribute.LIMIT_MODULES.equals(attribute.getName()))
+ return true;
+ }
+ return false;
+ }
+
public IClasspathEntry getClasspathEntry() {
if (fCachedEntry == null) {
fCachedEntry= newClasspathEntry();
@@ -226,12 +241,26 @@ public class CPListElement {
if (elem.getValue() != null) {
res.add(elem.getClasspathAttribute());
}
- } else if (elem.getValue() instanceof ModuleAddExport[]) {
+ } else if (elem.getValue() instanceof ModuleEncapsulationDetail[]) {
res.add(JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true")); //$NON-NLS-1$
- String encodedExports= ModuleAddExport.encode((ModuleAddExport[]) elem.getValue());
+
+ ModuleEncapsulationDetail[] detailValue= (ModuleEncapsulationDetail[]) elem.getValue();
+ String encodedPatch= ModuleEncapsulationDetail.encodeFiltered(detailValue, ModulePatch.class);
+ if (!encodedPatch.isEmpty()) {
+ res.add(JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, encodedPatch));
+ }
+ String encodedExports= ModuleEncapsulationDetail.encodeFiltered(detailValue, ModuleAddExport.class);
if (!encodedExports.isEmpty()) {
res.add(JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, encodedExports));
}
+ String encodedReads= ModuleEncapsulationDetail.encodeFiltered(detailValue, ModuleAddReads.class);
+ if (!encodedReads.isEmpty()) {
+ res.add(JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_READS, encodedReads));
+ }
+ String encodedLimits= ModuleEncapsulationDetail.encodeFiltered(detailValue, LimitModules.class);
+ if (!encodedLimits.isEmpty()) {
+ res.add(JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, encodedLimits));
+ }
}
}
}
@@ -411,6 +440,20 @@ public class CPListElement {
return res.toArray(new CPListElementAttribute[res.size()]);
}
+ public <T extends ModuleEncapsulationDetail> List<T> getModuleEncapsulationDetails(Class<T> clazz) {
+ Object moduleDetails= getAttribute(CPListElement.MODULE);
+ if (moduleDetails instanceof ModuleEncapsulationDetail[]) {
+ ModuleEncapsulationDetail[] details= (ModuleEncapsulationDetail[]) moduleDetails;
+ List<T> elements= new ArrayList<>(details.length);
+ for (int i= 0; i < details.length; i++) {
+ if (clazz.isInstance(details[i]))
+ elements.add(clazz.cast(details[i]));
+ }
+ return elements;
+ } else {
+ return Collections.emptyList();
+ }
+ }
private void createAttributeElement(String key, Object value, boolean builtIn) {
fChildren.add(new CPListElementAttribute(this, key, value, builtIn));
@@ -722,21 +765,27 @@ public class CPListElement {
IClasspathAttribute attrib= extraAttributes[i];
CPListElementAttribute attribElem= elem.findAttributeElement(attrib.getName());
if (attribElem == null) {
- if (!IClasspathAttribute.ADD_EXPORTS.equals(attrib.getName()) && !IClasspathAttribute.MODULE.equals(attrib.getName())) {
+ if (!isModuleAttribute(attrib.getName())) {
elem.createAttributeElement(attrib.getName(), attrib.getValue(), false);
}
} else {
Object value= attrib.getValue();
if (attrib.getName().equals(MODULE)) {
if (ModuleAttributeConfiguration.TRUE.equals(attrib.getValue())) {
- List<ModuleAddExport> exports = new ArrayList<>();
+ List<ModuleEncapsulationDetail> details= new ArrayList<>();
for (int j= 0; j < extraAttributes.length; j++) {
IClasspathAttribute otherAttrib= extraAttributes[j];
- if (IClasspathAttribute.ADD_EXPORTS.equals(otherAttrib.getName())) {
- exports.addAll(ModuleAddExport.fromMultiString(attribElem, otherAttrib.getValue()));
+ if (IClasspathAttribute.PATCH_MODULE.equals(otherAttrib.getName())) {
+ details.add(ModulePatch.fromString(attribElem, otherAttrib.getValue()));
+ } else if (IClasspathAttribute.ADD_EXPORTS.equals(otherAttrib.getName())) {
+ details.addAll(ModuleAddExport.fromMultiString(attribElem, otherAttrib.getValue()));
+ } else if (IClasspathAttribute.ADD_READS.equals(otherAttrib.getName())) {
+ details.addAll(ModuleAddReads.fromMultiString(attribElem, otherAttrib.getValue()));
+ } else if (IClasspathAttribute.LIMIT_MODULES.equals(otherAttrib.getName())) {
+ details.add(LimitModules.fromString(attribElem, otherAttrib.getValue()));
}
}
- value= exports.toArray(new ModuleAddExport[exports.size()]);
+ value= details.toArray(new ModuleEncapsulationDetail[details.size()]);
} else {
value= null;
}
@@ -749,6 +798,12 @@ public class CPListElement {
return elem;
}
+ private static boolean isModuleAttribute(String attributeName) {
+ return Stream.of(IClasspathAttribute.MODULE, IClasspathAttribute.LIMIT_MODULES,
+ IClasspathAttribute.PATCH_MODULE, IClasspathAttribute.ADD_EXPORTS, IClasspathAttribute.ADD_READS)
+ .anyMatch(attributeName::equals);
+ }
+
public static StringBuffer appendEncodePath(IPath path, StringBuffer buf) {
if (path != null) {
String str= path.toString();
@@ -819,10 +874,18 @@ public class CPListElement {
buf.append(((Boolean) elem.getValue()).booleanValue()).append(';');
} else if (MODULE.equals(key)) {
Object value= elem.getValue();
- if (value instanceof ModuleAddExport[]) {
+ if (value instanceof ModuleEncapsulationDetail[]) {
buf.append(MODULE+"=true;"); //$NON-NLS-1$
- for (ModuleAddExport export : ((ModuleAddExport[]) value))
- buf.append(IClasspathAttribute.ADD_EXPORTS+':'+export.toString()).append(';');
+ for (ModuleEncapsulationDetail detail : ((ModuleEncapsulationDetail[]) value)) {
+ if (detail instanceof ModulePatch)
+ buf.append(IClasspathAttribute.PATCH_MODULE+':'+detail.toString()).append(';');
+ if (detail instanceof ModuleAddExport)
+ buf.append(IClasspathAttribute.ADD_EXPORTS+':'+detail.toString()).append(';');
+ if (detail instanceof ModuleAddReads)
+ buf.append(IClasspathAttribute.ADD_READS+':'+detail.toString()).append(';');
+ if (detail instanceof LimitModules)
+ buf.append(IClasspathAttribute.LIMIT_MODULES+':'+detail.toString()).append(';');
+ }
} else {
buf.append(MODULE+"=false;"); //$NON-NLS-1$
}
@@ -966,9 +1029,9 @@ public class CPListElement {
}
CPListElementAttribute moduleAttribute= findAttributeElement(MODULE);
if (moduleAttribute == null) {
- createAttributeElement(MODULE, new ModuleAddExport[0], false);
+ createAttributeElement(MODULE, new ModuleEncapsulationDetail[0], true);
} else {
- moduleAttribute.setValue(new ModuleAddExport[0]);
+ moduleAttribute.setValue(new ModuleEncapsulationDetail[0]);
}
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListLabelProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListLabelProvider.java
index f7f9258030..60ef841688 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListLabelProvider.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListLabelProvider.java
@@ -53,6 +53,10 @@ import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.LimitModules;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModulePatch;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
public class CPListLabelProvider extends LabelProvider {
@@ -100,8 +104,14 @@ public class CPListLabelProvider extends LabelProvider {
} else if (element instanceof IAccessRule) {
IAccessRule rule= (IAccessRule) element;
return Messages.format(NewWizardMessages.CPListLabelProvider_access_rules_label, new String[] { AccessRulesLabelProvider.getResolutionLabel(rule.getKind()), BasicElementLabels.getPathLabel(rule.getPattern(), false)});
+ } else if (element instanceof ModulePatch) {
+ return Messages.format(NewWizardMessages.CPListLabelProvider_patch_module_full_label, new String[] { element.toString() });
} else if (element instanceof ModuleAddExport) {
return Messages.format(NewWizardMessages.CPListLabelProvider_add_exports_full_label, new String[] { element.toString() });
+ } else if (element instanceof ModuleAddReads) {
+ return Messages.format(NewWizardMessages.CPListLabelProvider_add_reads_full_label, new String[] { element.toString() });
+ } else if (element instanceof LimitModules) {
+ return Messages.format(NewWizardMessages.CPListLabelProvider_limitModules_full_label, new String[] { element.toString() });
}
return super.getText(element);
}
@@ -240,12 +250,24 @@ public class CPListLabelProvider extends LabelProvider {
return Messages.format(NewWizardMessages.CPListLabelProvider_ignore_optional_problems_label, arg);
} else if (key.equals(CPListElement.MODULE)) {
Object value= attrib.getValue();
- if (value instanceof ModuleAddExport[]) {
- int nExports= ((ModuleAddExport[]) value).length;
- if (nExports > 0)
+ if (value instanceof ModuleEncapsulationDetail[]) {
+ boolean limitModules= false;
+ boolean modifiesEncaps= false;
+ for (ModuleEncapsulationDetail detail : (ModuleEncapsulationDetail[]) value) {
+ if (detail instanceof LimitModules) {
+ limitModules= true;
+ } else {
+ modifiesEncaps= true;
+ }
+ }
+ if (modifiesEncaps) {
+ if (limitModules)
+ return NewWizardMessages.CPListLabelProvider_modular_limitsAndModifies_label;
return NewWizardMessages.CPListLabelProvider_modular_modifiesEncapsulation_label;
- else
- return NewWizardMessages.CPListLabelProvider_modular_label;
+ } else if (limitModules) {
+ return NewWizardMessages.CPListLabelProvider_modular_limitsModules_label;
+ }
+ return NewWizardMessages.CPListLabelProvider_modular_label;
} else {
return NewWizardMessages.CPListLabelProvider_not_modular_label;
}
@@ -478,8 +500,14 @@ public class CPListLabelProvider extends LabelProvider {
} else if (element instanceof IAccessRule) {
IAccessRule rule= (IAccessRule) element;
return AccessRulesLabelProvider.getResolutionImage(rule.getKind());
+ } else if (element instanceof ModulePatch) {
+ return fRegistry.get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB);
} else if (element instanceof ModuleAddExport) {
- return fSharedImages.getImage(ISharedImages.IMG_OBJS_ADD_EXPORTS);
+ return fRegistry.get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB);
+ } else if (element instanceof ModuleAddReads) {
+ return fRegistry.get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB);
+ } else if (element instanceof LimitModules) {
+ return fRegistry.get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB);
}
return null;
}
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 4c4a287f8a..4f8b52d7e6 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
@@ -182,7 +182,6 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
for (int i= 0; i < nElements; i++) {
CPListElement cpe= cpelements.get(i);
if (isEntryKind(cpe.getEntryKind())) {
- boolean isModular = false;
Object mod = cpe.getAttribute(CPListElement.MODULE);
if(mod==null) {
rootClasspath.addCPListElement(cpe);
@@ -366,8 +365,7 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
for (CPListElement cpListElement : elementsToAdd) {
Object attribute= cpListElement.getAttribute(IClasspathAttribute.MODULE);
if(attribute == null) {
- cpListElement.setAttribute(IClasspathAttribute.MODULE, new ModuleAddExport[0]);
-
+ cpListElement.setAttribute(IClasspathAttribute.MODULE, new ModuleEncapsulationDetail[0]);
}
}
}
@@ -500,8 +498,8 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
}
changedAttributes.add(key); // collect the changed attributes
}
- } else if (elem instanceof ModuleAddExport) {
- removeAddExport((ModuleAddExport) elem);
+ } else if (elem instanceof ModuleEncapsulationDetail) {
+ removeEncapsulationDetail((ModuleEncapsulationDetail) elem);
}
}
if (selElements.isEmpty()) {
@@ -571,7 +569,7 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
if (curr.getParentContainer() != null) {
return false;
}
- } else if (elem instanceof ModuleAddExport) {
+ } else if (elem instanceof ModuleEncapsulationDetail) {
return true;
} else { // unknown element
return false;
@@ -643,7 +641,7 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
}
}
} else if (key.equals(CPListElement.MODULE)) {
- if (showAddExportDialog(getShell(), elem)) {
+ if (showModuleDialog(getShell(), elem)) {
String[] changedAttributes= { CPListElement.MODULE };
attributeUpdated(selElement, changedAttributes);
@@ -835,13 +833,13 @@ public class LibrariesWorkbookPage extends BuildPathBasePage {
private void updateClasspathList() {
List<CPListElement> projelements= fLibrariesList.getElements();
- List<CPListElement> flattenedProjElements = new ArrayList<CPListElement>();
+ List<CPListElement> flattenedProjElements = new ArrayList<>();
for ( int i =0; i < projelements.size(); i++ ) {
CPListElement ele = projelements.get(i);
// if root node, collect the CPList elements
if(ele.isRootNodeForPath()) {
ArrayList<Object> children= ele.getChildren();
- for (Iterator iterator= children.iterator(); iterator.hasNext();) {
+ for (Iterator<?> iterator= children.iterator(); iterator.hasNext();) {
Object object= iterator.next();
if(object instanceof CPListElement) {
flattenedProjElements.add((CPListElement) object);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExport.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExport.java
deleted file mode 100644
index fb56f87816..0000000000
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExport.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2017 GK Software AG, and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * This is an implementation of an early-draft specification developed under the Java
- * Community Process (JCP) and is made available for testing and evaluation purposes
- * only. The code is not compatible with any specification of the JCP.
- *
- * Contributors:
- * Stephan Herrmann - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.ui.wizards.buildpaths;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
-
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-
-import org.eclipse.jdt.internal.ui.JavaPlugin;
-
-/**
- * Node in the tree of CPListElement et al, representing an add-exports module directive.
- */
-public class ModuleAddExport {
-
- public static ModuleAddExport fromString(CPListElementAttribute attribElem, String value) {
- int slash = value.indexOf('/');
- int equals = value.indexOf('=');
- if (slash != -1 && equals != -1 && equals > slash) {
- return new ModuleAddExport(value.substring(0, slash),
- value.substring(slash+1, equals),
- value.substring(equals+1),
- attribElem);
- }
- return null;
- }
-
- public static Collection<ModuleAddExport> fromMultiString(CPListElementAttribute attribElem, String values) {
- List<ModuleAddExport> exports= new ArrayList<>();
- for (String value : values.split(":")) { //$NON-NLS-1$
- ModuleAddExport export= fromString(attribElem, value);
- if (export != null)
- exports.add(export);
- }
- return exports;
- }
-
- public static String encode(ModuleAddExport[] exports) {
- StringBuilder buf= new StringBuilder();
- for (ModuleAddExport export : exports) {
- if (buf.length() > 0)
- buf.append(':');
- buf.append(export.toString());
- }
- return buf.toString();
- }
-
- public final String fSourceModule;
- public final String fPackage;
- public final String fTargetModules;
-
- private CPListElementAttribute fAttribElem;
-
- public ModuleAddExport(String sourceModule, String aPackage, String targetModules, CPListElementAttribute attribElem) {
- fSourceModule= sourceModule;
- fPackage= aPackage;
- fTargetModules= targetModules;
- fAttribElem= attribElem;
- }
-
- @Override
- public String toString() {
- return fSourceModule+'/'+fPackage+'='+fTargetModules;
- }
-
- public CPListElementAttribute getParent() {
- return fAttribElem;
- }
-
- /**
- * Retrieve the java element(s) targeted by a given classpath entry.
- * @param currentProject the Java project holding the classpath entry
- * @param path the path value of the classpath entry
- * @return either an array of {@link IPackageFragmentRoot} or a singleton array of {@link IJavaProject}
- * targeted by the given classpath entry, or {@code null} if no not found
- */
- public static IJavaElement[] getTargetJavaElements(IJavaProject currentProject, IPath path) {
- IResource member= ResourcesPlugin.getWorkspace().getRoot().findMember(path);
- if (member != null) {
- IJavaElement element= JavaCore.create(member);
- if (element != null)
- return new IJavaElement[] {element};
- } else if (path != null && path.isAbsolute()) {
- try {
- for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) {
- if (classpathEntry.getPath().equals(path)) {
- switch (classpathEntry.getEntryKind()) {
- case IClasspathEntry.CPE_LIBRARY:
- return new IJavaElement[] {currentProject.getPackageFragmentRoot(path.toString())};
- default:
- // keep looking
- }
- }
- }
- } catch (JavaModelException e) {
- JavaPlugin.log(e);
- }
- } else {
- try {
- for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) {
- if (classpathEntry.getPath().equals(path)) {
- return currentProject.findPackageFragmentRoots(classpathEntry);
- }
- }
- } catch (JavaModelException e) {
- JavaPlugin.log(e);
- }
- }
- return null;
- }
-}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsAttributeConfiguration.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsAttributeConfiguration.java
deleted file mode 100644
index dcf52b7d59..0000000000
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsAttributeConfiguration.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2017 GK Software AG, and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * This is an implementation of an early-draft specification developed under the Java
- * Community Process (JCP) and is made available for testing and evaluation purposes
- * only. The code is not compatible with any specification of the JCP.
- *
- * Contributors:
- * Stephan Herrmann - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.ui.wizards.buildpaths;
-
-import org.eclipse.swt.widgets.Shell;
-
-import org.eclipse.core.runtime.IPath;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-
-import org.eclipse.jdt.core.IClasspathAttribute;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.JavaCore;
-
-import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;
-import org.eclipse.jdt.ui.wizards.ClasspathAttributeConfiguration;
-
-import org.eclipse.jdt.internal.ui.JavaPluginImages;
-import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
-
-public class ModuleAddExportsAttributeConfiguration extends ClasspathAttributeConfiguration {
-
- public ModuleAddExportsAttributeConfiguration() {
- }
-
- @Override
- public ImageDescriptor getImageDescriptor(ClasspathAttributeAccess attribute) {
- return JavaPluginImages.DESC_OBJS_ADD_EXPORTS_ATTRIB;
- }
-
- @Override
- public String getNameLabel(ClasspathAttributeAccess attribute) {
- return NewWizardMessages.CPListLabelProvider_add_exports_full_label;
- }
-
- @Override
- public String getValueLabel(ClasspathAttributeAccess access) {
- return access.getClasspathAttribute().getValue();
- }
-
- @Override
- public boolean canEdit(ClasspathAttributeAccess attribute) {
- return true;
- }
-
- @Override
- public boolean canRemove(ClasspathAttributeAccess attribute) {
- return attribute.getClasspathAttribute().getValue() != null;
- }
-
- @Override
- public IClasspathAttribute performEdit(Shell shell, ClasspathAttributeAccess attribute) {
- String initialValue= attribute.getClasspathAttribute().getValue();
- IPath entryPath= attribute.getParentClasspassEntry().getPath();
- IJavaElement[] sourceElements= ModuleAddExport.getTargetJavaElements(attribute.getJavaProject(), entryPath);
- String newValue= BuildPathDialogAccess.configureAddExports(shell, sourceElements, initialValue);
- if(null == newValue) // Was the dialog cancelled?
- return null;
- return JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_READS, newValue);
- }
-
- @Override
- public IClasspathAttribute performRemove(ClasspathAttributeAccess attribute) {
- return JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_READS, null);
- }
-}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsBlock.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsBlock.java
index e92cf7fff7..46d0a0dbab 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsBlock.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsBlock.java
@@ -24,7 +24,6 @@ import java.util.function.Predicate;
import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
@@ -52,13 +51,12 @@ import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
-import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaPackageCompletionProcessor;
-import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaPrecomputedNamesAssistProcessor;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
@@ -242,7 +240,9 @@ public class ModuleAddExportsBlock {
LayoutUtil.setWidthHint(sourceModuleField, widthHint);
LayoutUtil.setHorizontalGrabbing(sourceModuleField);
BidiUtils.applyBidiProcessing(sourceModuleField, StructuredTextTypeHandlerFactory.JAVA);
- configureModuleContentAssist(fSourceModule.getTextControl(composite));
+ if (fSourceJavaElements != null) {
+ ModuleDialog.configureModuleContentAssist(fSourceModule.getTextControl(composite), moduleNames());
+ }
DialogField.createEmptySpace(composite, 2);
@@ -270,18 +270,6 @@ public class ModuleAddExportsBlock {
return composite;
}
- private void configureModuleContentAssist(Text textControl) {
- if (fSourceJavaElements == null || fSourceJavaElements.length <= 1) {
- return;
- }
- Set<String> moduleNames= moduleNames();
- if (!moduleNames.isEmpty()) {
- Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE);
- JavaPrecomputedNamesAssistProcessor processor= new JavaPrecomputedNamesAssistProcessor(moduleNames, image);
- ControlContentAssistHelper.createTextContentAssistant(textControl, processor);
- }
- }
-
private void configurePackageContentAssist(Text textControl) {
if (fSourceJavaElements == null || fSourceJavaElements.length == 0) {
return;
@@ -421,7 +409,7 @@ public class ModuleAddExportsBlock {
}
if (status == null) {
if (getPackageText().isEmpty()) { // not yet validated but empty?
- status= ModuleAddExportsDialog.newSilentError();
+ status= ModuleDialog.newSilentError();
} else {
status= Status.OK_STATUS;
}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsDialog.java
index 93d63b98af..7683c81af4 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddExportsDialog.java
@@ -23,7 +23,6 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.StatusDialog;
-import org.eclipse.jface.util.Util;
import org.eclipse.ui.PlatformUI;
@@ -33,6 +32,7 @@ import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
/**
* A dialog to configure add-exports of a library.
@@ -64,7 +64,7 @@ public class ModuleAddExportsDialog extends StatusDialog {
setTitle(NewWizardMessages.AddExportsDialog_title);
if (sourceJavaElements == null)
updateStatus(new Status(IStatus.WARNING, JavaPlugin.getPluginId(),
- NewWizardMessages.AddExportsDialog_notPersisted_warning));
+ NewWizardMessages.AddModuleDetailsDialog_notPersisted_warning));
}
/*
@@ -84,13 +84,9 @@ public class ModuleAddExportsDialog extends StatusDialog {
@Override
public void create() {
super.create();
- updateButtonsEnableState(newSilentError()); // silently disable OK button until user input is given
+ updateButtonsEnableState(ModuleDialog.newSilentError()); // silently disable OK button until user input is given
}
- public static Status newSilentError() {
- return new Status(IStatus.ERROR, JavaPlugin.getPluginId(), Util.ZERO_LENGTH_STRING);
- }
-
@Override
protected Control createDialogArea(Composite parent) {
Composite composite= (Composite) super.createDialogArea(parent);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsBlock.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsBlock.java
new file mode 100644
index 0000000000..1378134427
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsBlock.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2017 GK Software AG, and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.wizards.buildpaths;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.util.BidiUtils;
+
+import org.eclipse.ui.PlatformUI;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IModuleDescription;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+
+import org.eclipse.jdt.internal.corext.util.Messages;
+
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
+
+
+/**
+ * UI to define one additional exports (add-reads).
+ */
+public class ModuleAddReadsBlock {
+
+ private final IStatusChangeListener fContext;
+
+ private StringDialogField fSourceModule;
+ private StringDialogField fTargetModule;
+
+ private IStatus fSourceModuleStatus;
+
+ private Control fSWTWidget;
+
+ private final ModuleAddReads fInitialValue;
+
+ private IJavaElement[] fSourceJavaElements;
+
+ /**
+ * @param context listeners for status updates
+ * @param sourceJavaElements java element representing the source modules from where packages should be exported
+ * @param initialValue The value to edit
+ */
+ public ModuleAddReadsBlock(IStatusChangeListener context, IJavaElement[] sourceJavaElements, ModuleAddReads initialValue) {
+ fContext= context;
+ fInitialValue= initialValue;
+ fSourceJavaElements= sourceJavaElements;
+
+ fSourceModuleStatus= new StatusInfo();
+
+ IDialogFieldListener adapter= field -> addExportsDialogFieldChanged(field);
+
+ // create the dialog fields (no widgets yet)
+ fSourceModule= new StringDialogField();
+ fSourceModule.setDialogFieldListener(adapter);
+ fSourceModule.setLabelText(NewWizardMessages.AddReadsBlock_sourceModule_label);
+
+ fTargetModule= new StringDialogField();
+ fTargetModule.setDialogFieldListener(adapter);
+ fTargetModule.setLabelText(NewWizardMessages.AddReadsBlock_targetModule_label);
+
+ setDefaults();
+ }
+
+ private void setDefaults() {
+ if (fInitialValue != null) {
+ fSourceModule.setText(fInitialValue.fSourceModule);
+ if (!fInitialValue.fSourceModule.isEmpty() && (fSourceJavaElements == null || fSourceJavaElements.length <= 1)) {
+ fSourceModule.setEnabled(false);
+ }
+ fTargetModule.setText(fInitialValue.fTargetModule);
+ fTargetModule.setEnabled(true);
+ }
+ }
+
+ private Set<String> moduleNames() {
+ Set<String> moduleNames= new HashSet<>();
+ if (fSourceJavaElements != null) {
+ for (int i= 0; i < fSourceJavaElements.length; i++) {
+ if (fSourceJavaElements[i] instanceof IPackageFragmentRoot) {
+ IModuleDescription module= ((IPackageFragmentRoot) fSourceJavaElements[i]).getModuleDescription();
+ if (module != null) {
+ moduleNames.add(module.getElementName());
+ }
+ }
+ }
+ }
+ return moduleNames;
+ }
+
+ private String getSourceModuleText() {
+ return fSourceModule.getText().trim();
+ }
+
+ private String getTargetModulesText() {
+ return fTargetModule.getText().trim();
+ }
+
+ /**
+ * Gets the add-reads value entered by the user
+ * @return the add-reads value, or an empty string if any of the fields was left empty.
+ */
+ public String getValue() {
+ String sourceModule= getSourceModuleText();
+ String targetModules= getTargetModulesText();
+ if (sourceModule.isEmpty() || targetModules.isEmpty())
+ return ""; //$NON-NLS-1$
+ return sourceModule+'='+targetModules;
+ }
+
+ public ModuleAddReads getReads(CPListElementAttribute parentAttribute) {
+ String sourceModule= getSourceModuleText();
+ String targetModules= getTargetModulesText();
+ if (sourceModule.isEmpty() || targetModules.isEmpty())
+ return null;
+ return new ModuleAddReads(sourceModule, targetModules, parentAttribute);
+ }
+
+ /**
+ * Creates the control
+ * @param parent the parent
+ * @return the created control
+ */
+ public Control createControl(Composite parent) {
+ PixelConverter converter= new PixelConverter(parent);
+
+ fSWTWidget= parent;
+
+ Composite composite= new Composite(parent, SWT.NONE);
+
+ GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 2;
+ composite.setLayout(layout);
+
+
+ int widthHint= converter.convertWidthInCharsToPixels(60);
+
+ GridData gd= new GridData(GridData.FILL, GridData.BEGINNING, false, false, 2, 1);
+ gd.widthHint= converter.convertWidthInCharsToPixels(50);
+
+ Label message= new Label(composite, SWT.LEFT + SWT.WRAP);
+ message.setLayoutData(gd);
+ message.setText(NewWizardMessages.AddReadsBlock_message);
+
+ DialogField.createEmptySpace(composite, 2);
+
+ fSourceModule.doFillIntoGrid(composite, 2);
+ Text sourceModuleField= fSourceModule.getTextControl(null);
+ LayoutUtil.setWidthHint(sourceModuleField, widthHint);
+ LayoutUtil.setHorizontalGrabbing(sourceModuleField);
+ BidiUtils.applyBidiProcessing(sourceModuleField, StructuredTextTypeHandlerFactory.JAVA);
+ if (fSourceJavaElements != null) {
+ ModuleDialog.configureModuleContentAssist(fSourceModule.getTextControl(composite), moduleNames());
+ }
+
+ DialogField.createEmptySpace(composite, 2);
+
+ fTargetModule.doFillIntoGrid(composite, 2);
+ Text targetModulesField= fTargetModule.getTextControl(null);
+ LayoutUtil.setWidthHint(targetModulesField, widthHint);
+ LayoutUtil.setHorizontalGrabbing(targetModulesField);
+ BidiUtils.applyBidiProcessing(targetModulesField, StructuredTextTypeHandlerFactory.JAVA);
+ // TODO: content assist from all known modules?
+
+ DialogField.createEmptySpace(composite, 2);
+
+ Dialog.applyDialogFont(composite);
+
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.EXTERNAL_ANNOTATIONS_ATTACHMENT_DIALOG); // FIXME
+ return composite;
+ }
+
+ // ---------- IDialogFieldListener --------
+
+ private void addExportsDialogFieldChanged(DialogField field) {
+ if (fSWTWidget != null) {
+ if (field == fSourceModule && fSourceModule.isEnabled()) {
+ updateModuleStatus();
+ }
+ doStatusLineUpdate();
+ }
+ }
+
+ private void updateModuleStatus() {
+ fSourceModuleStatus= computeSourceModuleStatus(getSourceModuleText());
+ }
+
+ private IStatus computeSourceModuleStatus(String value) {
+ StatusInfo status= new StatusInfo();
+ if (value.isEmpty()) {
+ status.setError(NewWizardMessages.ModuleAddExportsBlock_sourceModuleEmpty_error);
+ return status;
+ }
+ if (moduleNames().contains(value)) {
+ return status;
+ }
+ status.setError(Messages.format(NewWizardMessages.ModuleAddExportsBlock_wrongSourceModule_error, value));
+ return status;
+ }
+
+ private void doStatusLineUpdate() {
+ IStatus status= null;
+ if (!fSourceModuleStatus.isOK()) {
+ status= fSourceModuleStatus; // priority
+ }
+ // target module is not (yet) validated
+ if (status == null) {
+ status= Status.OK_STATUS;
+ }
+ fContext.statusChanged(status);
+ }
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsDialog.java
new file mode 100644
index 0000000000..94239b1bd9
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleAddReadsDialog.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2017 GK Software AG, and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.wizards.buildpaths;
+
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.jface.dialogs.StatusDialog;
+
+import org.eclipse.ui.PlatformUI;
+
+import org.eclipse.jdt.core.IJavaElement;
+
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
+
+/**
+ * A dialog to configure add-reads of a library.
+ *
+ */
+public class ModuleAddReadsDialog extends StatusDialog {
+
+ private ModuleAddReadsBlock fAddReadsBlock;
+
+ /**
+ * Creates an instance. After <code>open</code>, the edited export can be accessed using {@code #getResult()}
+ * or {@code #getReads()}.
+ *
+ * @param parent Parent shell for the dialog
+ * @param sourceJavaElements java elements representing the source modules for which more reads should be added
+ * @param value The value to edit.
+ */
+ public ModuleAddReadsDialog(Shell parent, IJavaElement[] sourceJavaElements, ModuleAddReads value) {
+ super(parent);
+
+ IStatusChangeListener listener= new IStatusChangeListener() {
+ @Override
+ public void statusChanged(IStatus status) {
+ updateStatus(status);
+ }
+ };
+ fAddReadsBlock= new ModuleAddReadsBlock(listener, sourceJavaElements, value);
+
+ setTitle(NewWizardMessages.AddReadsDialog_title);
+ if (sourceJavaElements == null)
+ updateStatus(new Status(IStatus.WARNING, JavaPlugin.getPluginId(),
+ NewWizardMessages.AddModuleDetailsDialog_notPersisted_warning));
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.Dialog#isResizable()
+ */
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.EXTERNAL_ANNOTATIONS_ATTACHMENT_DIALOG); // FIXME
+ }
+
+ @Override
+ public void create() {
+ super.create();
+ updateButtonsEnableState(ModuleDialog.newSilentError()); // silently disable OK button until user input is given
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite= (Composite) super.createDialogArea(parent);
+
+ Control inner= createAddReadsControls(composite);
+ inner.setLayoutData(new GridData(GridData.FILL_BOTH));
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ /**
+ * Creates the controls for the add-exports configuration.
+ *
+ * @param composite the parent composite
+ * @return the control
+ */
+ protected Control createAddReadsControls(Composite composite) {
+ return fAddReadsBlock.createControl(composite);
+ }
+
+ /**
+ * Returns the configured export value.
+ *
+ * @return the configured export value, or an empty string if no export was configured.
+ */
+ public String getResult() {
+ return fAddReadsBlock.getValue();
+ }
+
+ /**
+ * Returns the configured export value.
+ * @param parentAttribute the "module" attribute to which this export is associated
+ *
+ * @return the configured export value, or {@code null} if no export was configured.
+ */
+ public ModuleAddReads getReads(CPListElementAttribute parentAttribute) {
+ return fAddReadsBlock.getReads(parentAttribute);
+ }
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDialog.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDialog.java
index ae658097a8..3a7f53489f 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDialog.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleDialog.java
@@ -14,26 +14,49 @@
*******************************************************************************/
package org.eclipse.jdt.internal.ui.wizards.buildpaths;
+import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
+
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
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.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.StatusDialog;
+import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.util.BidiUtils;
+import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.PlatformUI;
@@ -46,6 +69,7 @@ import org.eclipse.jdt.core.IModuleDescription;
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.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
@@ -55,20 +79,60 @@ import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
+import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
+import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaPrecomputedNamesAssistProcessor;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.LimitModules;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddExport;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModuleAddReads;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail.ModulePatch;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
-import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
public class ModuleDialog extends StatusDialog {
private static final String NO_NAME= ""; //$NON-NLS-1$
- public class AddExportsLabelProvider extends LabelProvider implements ITableLabelProvider {
+ static class ListContentProvider implements IStructuredContentProvider {
+ List<?> fContents;
+
+ @Override
+ public Object[] getElements(Object input) {
+ if (fContents != null && fContents == input)
+ return fContents.toArray();
+ return new Object[0];
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (newInput instanceof List<?>)
+ fContents= (List<?>)newInput;
+ else
+ fContents= null;
+ }
+ }
+
+ static class ModulesLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ return JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE);
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ return element.toString();
+ }
+
+ }
+
+ public class AddDetailsLabelProvider extends LabelProvider implements ITableLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
@@ -78,7 +142,7 @@ public class ModuleDialog extends StatusDialog {
@Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof ModuleAddExport) {
- ModuleAddExport export = (ModuleAddExport) element;
+ ModuleAddExport export= (ModuleAddExport) element;
switch (columnIndex) {
case 0: return export.fSourceModule;
case 1: return export.fPackage;
@@ -86,6 +150,14 @@ public class ModuleDialog extends StatusDialog {
default:
throw new IllegalArgumentException("Illegal column index "+columnIndex); //$NON-NLS-1$
}
+ } else if (element instanceof ModuleAddReads) {
+ ModuleAddReads reads= (ModuleAddReads) element;
+ switch (columnIndex) {
+ case 0: return reads.fSourceModule;
+ case 1: return reads.fTargetModule;
+ default:
+ throw new IllegalArgumentException("Illegal column index "+columnIndex); //$NON-NLS-1$
+ }
}
return NO_NAME;
}
@@ -93,10 +165,36 @@ public class ModuleDialog extends StatusDialog {
}
private final SelectionButtonDialogField fIsModuleCheckbox;
+
+ static class ModuleList {
+ TableViewer fViewer;
+ List<String> fNames;
+ public ModuleList(List<String> names) {
+ fNames= names;
+ }
+ }
+ private ModuleList[] fModuleLists= new ModuleList[3];
+ private static final int IDX_AVAILABLE= 0;
+ private static final int IDX_INCLUDED= 1;
+ private static final int IDX_IMPLICITLY_INCLUDED= 2;
+
+ private Button fAddIncludedButton;
+ private Button fRemoveIncludedButton;
+ private Button fPromoteIncludedButton;
+
+ private final SelectionButtonDialogField fIsPatchCheckbox;
+ private final StringDialogField fPatchedModule;
+
private final ListDialogField<ModuleAddExport> fAddExportsList;
+
+ private final ListDialogField<ModuleAddReads> fAddReadsList;
+
private final CPListElement fCurrCPElement;
/** The element(s) targeted by the current CP entry, which will be the source module(s) of the added exports. */
private IJavaElement[] fJavaElements;
+ private Set<String> fModuleNames;
+
+ private Map<String,List<String>> fModule2RequiredModules;
private static final int IDX_ADD= 0;
private static final int IDX_EDIT= 1;
@@ -107,139 +205,94 @@ public class ModuleDialog extends StatusDialog {
super(parent);
fCurrCPElement= entryToEdit;
+ fJavaElements= selectedElements;
setTitle(NewWizardMessages.ModuleDialog_title);
fIsModuleCheckbox= new SelectionButtonDialogField(SWT.CHECK);
fIsModuleCheckbox.setLabelText(NewWizardMessages.ModuleDialog_defines_modules_label);
fIsModuleCheckbox.setSelection(entryToEdit.getAttribute(CPListElement.MODULE) != null);
- fIsModuleCheckbox.setDialogFieldListener(new AddExportsAdapter());
+ fIsModuleCheckbox.setDialogFieldListener(field -> doSelectionChangedAllLists());
- if (fCurrCPElement.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
- IPackageFragmentRoot[] roots= findRoots(fCurrCPElement);
- if (roots.length > 1 && roots[0].getModuleDescription() != null)
- fIsModuleCheckbox.setEnabled(false); // assume multi-module container is Java 9 JRE
- }
+ // -- contents page initialized in createContentsTab()
- fAddExportsList= createListContents(entryToEdit);
- doSelectionChanged(fAddExportsList);
+ // -- details page:
- fJavaElements= selectedElements;
- }
+ fIsPatchCheckbox= new SelectionButtonDialogField(SWT.CHECK);
+ fIsPatchCheckbox.setLabelText(NewWizardMessages.ModuleDialog_patches_module_label);
+ fIsPatchCheckbox.setDialogFieldListener(field -> doPatchSelectionChanged(field));
- private IPackageFragmentRoot[] findRoots(CPListElement element) {
- IClasspathEntry entry= element.getClasspathEntry();
- IPackageFragmentRoot[] roots= element.getJavaProject().findPackageFragmentRoots(entry);
- if (roots.length == 0) {
- // 2nd attempt in case "module=true" is not explicit on the real cp entry:
- entry = copyCPEntryWithoutModuleAttribute(entry);
- if (entry != null)
- roots= element.getJavaProject().findPackageFragmentRoots(entry);
- }
- return roots;
- }
+ fPatchedModule= new StringDialogField();
+ fPatchedModule.setLabelText(NewWizardMessages.ModuleDialog_patched_module_label);
+ fPatchedModule.setDialogFieldListener(field -> validateDetails(field));
- private IClasspathEntry copyCPEntryWithoutModuleAttribute(IClasspathEntry entry) {
- IClasspathAttribute[] oldAttributes= entry.getExtraAttributes();
- IClasspathAttribute[] newAttributes= new IClasspathAttribute[oldAttributes.length];
- int count= 0;
- for (int i= 0; i < oldAttributes.length; i++) {
- if (!oldAttributes[i].getName().equals(IClasspathAttribute.MODULE))
- newAttributes[count++]= oldAttributes[i];
- }
- if (count == oldAttributes.length)
- return null;
- newAttributes= count == 0 ? new IClasspathAttribute[0] : Arrays.copyOf(newAttributes, count);
- return JavaCore.newContainerEntry(entry.getPath(), entry.getAccessRules(), newAttributes, entry.isExported());
+ fAddExportsList= createDetailListContents(entryToEdit, NewWizardMessages.ModuleDialog_exports_label, new AddExportsAdapter(), ModuleAddExport.class);
+ fAddReadsList= createDetailListContents(entryToEdit, NewWizardMessages.ModuleDialog_reads_label, new AddReadsAdapter(), ModuleAddReads.class);
+
+ initializeValues();
+
+ doPatchSelectionChanged(fIsPatchCheckbox);
+ doSelectionChangedAllLists();
}
- /*
- * @see org.eclipse.jface.dialogs.Dialog#isResizable()
- * @since 3.4
- */
@Override
protected boolean isResizable() {
return true;
}
- private ListDialogField<ModuleAddExport> createListContents(CPListElement entryToEdit) {
- String label= NewWizardMessages.ModuleDialog_exports_label;
+ private <T extends ModuleEncapsulationDetail> ListDialogField<T> createDetailListContents(CPListElement entryToEdit, String label, ListAdapter<T> adapter, Class<T> clazz) {
String[] buttonLabels= new String[] {
- NewWizardMessages.ModuleDialog_exports_add,
- NewWizardMessages.ModuleDialog_exports_edit,
- NewWizardMessages.ModuleDialog_exports_remove
+ NewWizardMessages.ModuleDialog_detail_add,
+ NewWizardMessages.ModuleDialog_detail_edit,
+ NewWizardMessages.ModuleDialog_detail_remove
};
- AddExportsAdapter adapter= new AddExportsAdapter();
- AddExportsLabelProvider labelProvider= new AddExportsLabelProvider();
+ AddDetailsLabelProvider labelProvider= new AddDetailsLabelProvider();
- ListDialogField<ModuleAddExport> exportsList= new ListDialogField<>(adapter, buttonLabels, labelProvider);
- exportsList.setDialogFieldListener(adapter);
+ ListDialogField<T> detailsList= new ListDialogField<>(adapter, buttonLabels, labelProvider);
- exportsList.setLabelText(label);
- exportsList.setRemoveButtonIndex(IDX_REMOVE);
- exportsList.enableButton(IDX_EDIT, false);
+ detailsList.setLabelText(label);
+ detailsList.setRemoveButtonIndex(IDX_REMOVE);
+ detailsList.enableButton(IDX_EDIT, false);
- ArrayList<ModuleAddExport> elements;
- Object moduleDetails= entryToEdit.getAttribute(CPListElement.MODULE);
- if (moduleDetails instanceof ModuleAddExport[]) {
- ModuleAddExport[] exports= (ModuleAddExport[]) moduleDetails;
- elements= new ArrayList<>(exports.length);
- for (int i= 0; i < exports.length; i++) {
- elements.add(exports[i]);
- }
- } else {
- elements= new ArrayList<>(0);
- }
- exportsList.setElements(elements);
- exportsList.selectFirstElement();
- return exportsList;
+ detailsList.setElements(entryToEdit.getModuleEncapsulationDetails(clazz));
+ detailsList.selectFirstElement();
+ return detailsList;
}
-
@Override
protected Control createDialogArea(Composite parent) {
Composite composite= (Composite) super.createDialogArea(parent);
+ GridLayout layout= new GridLayout(1, true);
+ layout.marginBottom= 0;
+ composite.setLayout(layout);
- Composite inner= new Composite(composite, SWT.NONE);
- inner.setFont(composite.getFont());
-
- GridLayout layout= new GridLayout();
- layout.marginHeight= 0;
- layout.marginWidth= 0;
- layout.numColumns= 2;
- inner.setLayout(layout);
- inner.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- Label description= new Label(inner, SWT.WRAP);
+ Label description= new Label(composite, SWT.WRAP);
description.setText(getDescriptionString());
- GridData data= new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
+ GridData data= new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1);
data.widthHint= convertWidthInCharsToPixels(100);
description.setLayoutData(data);
- fIsModuleCheckbox.doFillIntoGrid(inner, 2);
+ fIsModuleCheckbox.doFillIntoGrid(composite, 3);
- ColumnLayoutData[] columnDta= {
- new ColumnWeightData(2),
- new ColumnWeightData(3),
- new ColumnWeightData(2),
- };
- String[] headers= {
- NewWizardMessages.ModuleDialog_source_module_header,
- NewWizardMessages.ModuleDialog_package_header,
- NewWizardMessages.ModuleDialog_target_modules_header
- };
- fAddExportsList.setTableColumns(new ListDialogField.ColumnsDescription(columnDta, headers, true));
- fAddExportsList.doFillIntoGrid(inner, 3);
+ TabFolder tabFolder= new TabFolder(composite, SWT.NONE);
+ tabFolder.setFont(composite.getFont());
+ tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- LayoutUtil.setHorizontalSpan(fAddExportsList.getLabelControl(null), 2);
+ final TabItem tabItemContents= new TabItem(tabFolder, SWT.NONE);
+ tabItemContents.setText(NewWizardMessages.ModuleDialog_contents_tab);
+ tabItemContents.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE));
+ tabItemContents.setControl(createContentsTab(tabFolder));
- data= (GridData) fAddExportsList.getListControl(null).getLayoutData();
- data.grabExcessHorizontalSpace= true;
- data.heightHint= SWT.DEFAULT;
+ final TabItem tabItemDetails= new TabItem(tabFolder, SWT.NONE);
+ tabItemDetails.setText(NewWizardMessages.ModuleDialog_details_tab);
+ tabItemDetails.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE_ATTRIB));
+ tabItemDetails.setControl(createDetailsTab(tabFolder));
+
+ tabFolder.addSelectionListener(widgetSelectedAdapter(e -> validateTab(e.widget, tabItemContents, tabItemDetails)));
applyDialogFont(composite);
return composite;
@@ -267,69 +320,480 @@ public class ModuleDialog extends StatusDialog {
return Messages.format(desc, name);
}
+ Composite createContentsTab(Composite parent) {
+ Composite contentsPage= new Composite(parent, SWT.NONE);
+ contentsPage.setFont(parent.getFont());
+ applyDialogFont(contentsPage);
+
+ GridLayout layout= new GridLayout();
+ layout.marginTop= 5;
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 3; // list , buttons , list
+ contentsPage.setLayout(layout);
+ contentsPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ // top
+ createContentListContents(contentsPage,
+ NewWizardMessages.ModuleDialog_availableModules_list,
+ NewWizardMessages.ModuleDialog_availableModules_tooltip,
+ IDX_AVAILABLE, IDX_INCLUDED);
+ createHorizontalButtons(contentsPage);
+ createContentListContents(contentsPage,
+ NewWizardMessages.ModuleDialog_explicitlyIncludedModules_list,
+ NewWizardMessages.ModuleDialog_explicitlyIncludedModules_tooltip,
+ IDX_INCLUDED, IDX_AVAILABLE);
+
+ // bottom
+ Label spacer= new Label(contentsPage, SWT.NONE);
+ GridData gd= new GridData();
+ gd.horizontalSpan= 2;
+ spacer.setLayoutData(gd);
+
+ Composite lowerRight= new Composite(contentsPage, SWT.NONE);
+ lowerRight.setLayout(new GridLayout(1, true));
+ gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ lowerRight.setLayoutData(gd);
+
+ createVerticalButton(lowerRight);
+ createContentListContents(lowerRight,
+ NewWizardMessages.ModuleDialog_implicitelyIncludedModules_list,
+ NewWizardMessages.ModuleDialog_implicitlyIncludedModule_tooltip,
+ IDX_IMPLICITLY_INCLUDED, IDX_INCLUDED);
+
+ validateContents();
+
+ return contentsPage;
+ }
+
+ Composite createDetailsTab(Composite parent) {
+ Composite detailPage= new Composite(parent, SWT.NONE);
+ detailPage.setFont(parent.getFont());
+ applyDialogFont(detailPage);
- protected void doCustomButtonPressed(ListDialogField<ModuleAddExport> field, int index) {
- if (index == IDX_ADD) {
- addEntry(field);
- } else if (index == IDX_EDIT) {
- editEntry(field);
+ GridLayout layout= new GridLayout();
+ layout.marginTop= 5;
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.numColumns= 3;
+ detailPage.setLayout(layout);
+ detailPage.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fIsPatchCheckbox.doFillIntoGrid(detailPage, 3);
+ fPatchedModule.doFillIntoGrid(detailPage, 2);
+ GridData data= (GridData) fPatchedModule.getLabelControl(null).getLayoutData();
+ data.horizontalIndent= LayoutUtil.getIndent();
+
+ Text patchedModuleText= fPatchedModule.getTextControl(null);
+ BidiUtils.applyBidiProcessing(patchedModuleText, StructuredTextTypeHandlerFactory.JAVA);
+ if (fJavaElements != null) {
+ configureModuleContentAssist(patchedModuleText, moduleNames());
}
+
+ ColumnLayoutData[] columnDta= {
+ new ColumnWeightData(2),
+ new ColumnWeightData(3),
+ new ColumnWeightData(2),
+ };
+ String[] headers= {
+ NewWizardMessages.ModuleDialog_source_module_header,
+ NewWizardMessages.ModuleDialog_package_header,
+ NewWizardMessages.ModuleDialog_target_module_header
+ };
+ fAddExportsList.setTableColumns(new ListDialogField.ColumnsDescription(columnDta, headers, true));
+
+ fAddExportsList.doFillIntoGrid(detailPage, 4);
+
+ LayoutUtil.setHorizontalSpan(fAddExportsList.getLabelControl(null), 3);
+
+ data= (GridData) fAddExportsList.getListControl(null).getLayoutData();
+ data.grabExcessHorizontalSpace= true;
+ data.heightHint= SWT.DEFAULT;
+
+ columnDta= new ColumnWeightData[] {
+ new ColumnWeightData(1),
+ new ColumnWeightData(1),
+ };
+ headers= new String[] {
+ NewWizardMessages.ModuleDialog_source_module_header,
+ NewWizardMessages.ModuleDialog_target_module_header
+ };
+ fAddReadsList.setTableColumns(new ListDialogField.ColumnsDescription(columnDta, headers, true));
+
+ fAddReadsList.doFillIntoGrid(detailPage, 4);
+
+ LayoutUtil.setHorizontalSpan(fAddReadsList.getLabelControl(null), 3);
+
+ data= (GridData) fAddReadsList.getListControl(null).getLayoutData();
+ data.grabExcessHorizontalSpace= true;
+ data.heightHint= SWT.DEFAULT;
+ return detailPage;
+ }
+
+ // ======== widgets for the Contents tab: ========
+
+ private void createContentListContents(Composite parent, String title, String tooltip, int idx, int targetIdx) {
+ Composite box= new Composite(parent, SWT.NONE);
+ GridLayout layout= new GridLayout(1, false);
+ layout.marginBottom= 0;
+ box.setLayout(layout);
+ GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.minimumWidth= 0;
+ box.setLayoutData(gd);
+
+ Label label= new Label(box, SWT.NONE);
+ label.setText(title);
+ label.setToolTipText(tooltip);
+
+ TableViewer tableViewer= new TableViewer(box, SWT.MULTI | SWT.BORDER);
+ tableViewer.setContentProvider(new ListContentProvider());
+ tableViewer.setLabelProvider(new ModulesLabelProvider());
+ tableViewer.addDoubleClickListener(e -> moveModuleEntry(idx, targetIdx));
+ tableViewer.setInput(fModuleLists[idx].fNames);
+ tableViewer.addSelectionChangedListener(e -> validateContents());
+ tableViewer.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ return ((String)e1).compareTo((String)e2);
+ }
+ });
+
+ PixelConverter converter= new PixelConverter(parent);
+ gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.widthHint= converter.convertWidthInCharsToPixels(30);
+ gd.heightHint= converter.convertHeightInCharsToPixels(6);
+ tableViewer.getControl().setLayoutData(gd);
+
+ fModuleLists[idx].fViewer= tableViewer;
}
- protected void doDoubleClicked(ListDialogField<ModuleAddExport> field) {
- editEntry(field);
+ private void createHorizontalButtons(Composite parent) {
+ org.eclipse.ui.ISharedImages sharedImages= JavaPlugin.getDefault().getWorkbench().getSharedImages();
+
+ Composite box= new Composite(parent, SWT.NONE);
+ box.setLayout(new GridLayout(1, true));
+
+ fAddIncludedButton= new Button(box, SWT.PUSH);
+ fAddIncludedButton.setImage(sharedImages.getImage(org.eclipse.ui.ISharedImages.IMG_TOOL_FORWARD));
+ fAddIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_addToIncluded_tooltip);
+ fAddIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_AVAILABLE, IDX_INCLUDED)));
+
+ fRemoveIncludedButton= new Button(box, SWT.PUSH);
+ fRemoveIncludedButton.setImage(sharedImages.getImage(org.eclipse.ui.ISharedImages.IMG_TOOL_BACK));
+ fRemoveIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_removeFromIncluded_tooltip);
+ fRemoveIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_INCLUDED, IDX_AVAILABLE)));
}
- protected void doSelectionChanged(ListDialogField<ModuleAddExport> field) {
+ private void createVerticalButton(Composite parent) {
+ fPromoteIncludedButton= new Button(parent, SWT.PUSH);
+ fPromoteIncludedButton.setImage(JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_BUTTON_MOVE_UP));
+ fPromoteIncludedButton.setToolTipText(NewWizardMessages.ModuleDialog_addToExplicitlyIncluded_tooltip);
+ fPromoteIncludedButton.addSelectionListener(widgetSelectedAdapter(e -> moveModuleEntry(IDX_IMPLICITLY_INCLUDED, IDX_INCLUDED)));
+ GridData gd= new GridData();
+ gd.horizontalAlignment= SWT.CENTER;
+ fPromoteIncludedButton.setLayoutData(gd);
+ }
+
+ private boolean canRemoveIncludedModules() {
+ if (fModuleLists[IDX_INCLUDED].fViewer.getSelection().isEmpty())
+ return false;
+ return fModuleLists[IDX_INCLUDED].fNames.size() + fModuleLists[IDX_AVAILABLE].fNames.size() > 1;
+ }
+
+ private void moveModuleEntry(int sourceIdx, int targetIdx) {
+ ISelection selection= fModuleLists[sourceIdx].fViewer.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ if (sourceIdx == IDX_INCLUDED && !canRemoveIncludedModules()) {
+ return;
+ }
+ List<String> sourceList= fModuleLists[sourceIdx].fNames;
+ List<String> targetList= fModuleLists[targetIdx].fNames;
+ for (Iterator<?> iter= ((IStructuredSelection) selection).iterator(); iter.hasNext();) {
+ Object selected= iter.next();
+ if (selected instanceof String) {
+ sourceList.remove(selected);
+ targetList.add((String) selected);
+ }
+ }
+ updateImplicitlyIncluded();
+ fModuleLists[IDX_AVAILABLE].fViewer.refresh();
+ fModuleLists[IDX_INCLUDED].fViewer.refresh();
+ fModuleLists[IDX_IMPLICITLY_INCLUDED].fViewer.refresh();
+ validateContents();
+ }
+ }
+
+ public static void configureModuleContentAssist(Text textControl, Set<String> moduleNames) {
+ if (moduleNames.size() == 1) {
+ textControl.setText(moduleNames.iterator().next());
+ } else if (!moduleNames.isEmpty()) {
+ Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_MODULE);
+ JavaPrecomputedNamesAssistProcessor processor= new JavaPrecomputedNamesAssistProcessor(moduleNames, image);
+ ControlContentAssistHelper.createTextContentAssistant(textControl, processor);
+ }
+ }
+
+ // ======== updating & validation: ========
+
+ protected void doPatchSelectionChanged(DialogField field) {
+ fPatchedModule.setEnabled(fIsPatchCheckbox.isSelected() && moduleNames().size() != 1);
+ validateDetails(field);
+ }
+
+ protected void doSelectionChangedAllLists() {
+ doSelectionChanged(fAddExportsList);
+ doSelectionChanged(fAddReadsList);
+ }
+
+ protected void doSelectionChanged(ListDialogField<? extends ModuleEncapsulationDetail> field) {
boolean isModular= fIsModuleCheckbox.isSelected();
- List<ModuleAddExport> selected= field.getSelectedElements();
+ List<? extends ModuleEncapsulationDetail> selected= field.getSelectedElements();
field.enableButton(IDX_ADD, isModular);
field.enableButton(IDX_EDIT, isModular && canEdit(selected));
field.enableButton(IDX_REMOVE, isModular && selected.size() > 0);
- validate();
+ validateDetails(field);
}
- private boolean canEdit(List<ModuleAddExport> selected) {
+ private boolean canEdit(List<? extends ModuleEncapsulationDetail> selected) {
return selected.size() == 1;
}
- private void validate() {
+ private void validateTab(Widget widget, Widget contentItem, Widget detailsItem) {
+ if (widget instanceof TabFolder) {
+ TabItem[] selected= ((TabFolder) widget).getSelection();
+ for (TabItem selectedItem : selected) {
+ if (selectedItem == contentItem) {
+ validateContents();
+ return;
+ } else if (selectedItem == detailsItem) {
+ validateDetails(null);
+ return;
+ }
+ }
+ }
+ }
+
+ private void validateContents() {
+ fAddIncludedButton.setEnabled(!fModuleLists[IDX_AVAILABLE].fViewer.getSelection().isEmpty());
+ fRemoveIncludedButton.setEnabled(canRemoveIncludedModules());
+ fPromoteIncludedButton.setEnabled(!fModuleLists[IDX_IMPLICITLY_INCLUDED].fViewer.getSelection().isEmpty());
+ IStatus status= computeContentsStatus();
+ updateStatus(status);
+ if (status.isOK()) {
+ status= computeDetailsStatus(null);
+ if (status.getSeverity() == IStatus.ERROR) {
+ updateStatus(new StatusInfo(IStatus.ERROR, NewWizardMessages.ModuleDialog_errorOnDetailsTab_error));
+ }
+ }
+ }
+
+ private IStatus computeContentsStatus() {
+ StatusInfo info= new StatusInfo();
+ if (fModuleLists[IDX_INCLUDED].fNames.isEmpty()) {
+ info.setError(NewWizardMessages.ModuleDialog_mustIncludeModule_error);
+ } else if (fModuleLists[IDX_INCLUDED].fNames.size() + fModuleLists[IDX_AVAILABLE].fNames.size() == 1) {
+ info.setInfo(NewWizardMessages.ModuleDialog_cannotLimitSingle_error);
+ }
+ return info;
+ }
+
+ private void validateDetails(DialogField field) {
+ IStatus status= computeDetailsStatus(field);
+ updateStatus(status);
+ if (status.isOK()) {
+ status= computeContentsStatus();
+ if (status.getSeverity() == IStatus.ERROR) {
+ updateStatus(new StatusInfo(IStatus.ERROR, NewWizardMessages.ModuleDialog_errorOnContentsTab_error));
+ }
+ }
+ }
+
+ private StatusInfo computeDetailsStatus(DialogField field) {
Set<String> packages= new HashSet<>();
StatusInfo status= new StatusInfo();
- for (ModuleAddExport export : fAddExportsList.getElements()) {
- if (!packages.add(export.fPackage)) {
- status.setError(Messages.format(NewWizardMessages.ModuleDialog_duplicatePackage_error, export.fPackage));
- break;
+ if (fIsPatchCheckbox.isSelected()) {
+ String patchedModule= fPatchedModule.getText().trim();
+ if (patchedModule.isEmpty()) {
+ if (field == fIsPatchCheckbox) {
+ status= newSilentError(); // silently disable OK button until user input is given
+ } else {
+ status.setError(NewWizardMessages.ModuleDialog_missingPatch_error);
+ }
+ Shell shell= getShell();
+ if (shell != null) {
+ fPatchedModule.getTextControl(shell).setFocus();
+ }
+ } else if (!moduleNames().isEmpty() && !moduleNames().contains(patchedModule)) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_wrongPatch_error, patchedModule));
+ } else if (isModuleExcluded(patchedModule)) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_patchedModuleExcluded_error, patchedModule));
}
}
- updateStatus(status);
+ if (status.isOK()) {
+ for (ModuleAddExport export : fAddExportsList.getElements()) {
+ if (!packages.add(export.fPackage)) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_duplicatePackage_error, export.fPackage));
+ break;
+ }
+ if (isModuleExcluded(export.fSourceModule)) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_exportSourceModuleExcluded_error,
+ new String[]{ export.fPackage, export.fSourceModule }));
+ }
+ }
+ }
+ if (status.isOK()) {
+ Set<String> readModules= new HashSet<>();
+ for (ModuleAddReads reads : fAddReadsList.getElements()) {
+ if (!readModules.add(reads.toString())) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_duplicateReads_error, reads.toString()));
+ break;
+ }
+ if (isModuleExcluded(reads.fSourceModule)) {
+ status.setError(Messages.format(NewWizardMessages.ModuleDialog_readsSourceModuleExcluded_error,
+ reads.fSourceModule));
+ }
+ }
+ }
+ return status;
+ }
+
+ private boolean isModuleExcluded(String moduleName) {
+ return fModuleLists[IDX_AVAILABLE].fNames.contains(moduleName);
}
- private void editEntry(ListDialogField<ModuleAddExport> field) {
+ // ======== operations on values, i.e., classpath entries, modules and packages: ========
- List<ModuleAddExport> selElements= field.getSelectedElements();
- if (selElements.size() != 1) {
- return;
+ private void initializeValues() {
+ fModule2RequiredModules= new HashMap<>();
+
+ List<String> availableNames= new ArrayList<>(moduleNames());
+ List<String> includedNames= new ArrayList<>();
+ List<LimitModules> limits= fCurrCPElement.getModuleEncapsulationDetails(LimitModules.class);
+ if (!limits.isEmpty()) {
+ for (LimitModules limitModules : limits) {
+ includedNames.addAll(limitModules.fExplicitlyIncludedModules);
+ availableNames.removeAll(limitModules.fExplicitlyIncludedModules);
+ }
+ } else {
+ includedNames= availableNames;
+ availableNames= new ArrayList<>();
+ }
+ fModuleLists[IDX_AVAILABLE]= new ModuleList(availableNames);
+ fModuleLists[IDX_INCLUDED]= new ModuleList(new ArrayList<>(includedNames));
+ fModuleLists[IDX_IMPLICITLY_INCLUDED]= new ModuleList(new ArrayList<>());
+ updateImplicitlyIncluded();
+
+ // access to widgets may trigger validation, which needs all values to be initialized (non-null):
+
+ if (fCurrCPElement.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+ IPackageFragmentRoot[] roots= findRoots(fCurrCPElement);
+ if (roots.length > 1 && roots[0].getModuleDescription() != null)
+ fIsModuleCheckbox.setEnabled(false); // assume multi-module container is Java 9 JRE
}
- ModuleAddExport export= selElements.get(0);
- ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, export);
- if (dialog.open() == Window.OK) {
- ModuleAddExport newExport= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
- if (newExport != null) {
- field.replaceElement(export, newExport);
- } else {
- field.removeElement(export);
+
+ List<ModulePatch> patchedModules= fCurrCPElement.getModuleEncapsulationDetails(ModulePatch.class);
+ fIsPatchCheckbox.setSelection(!patchedModules.isEmpty());
+
+ if (patchedModules.size() == 1)
+ fPatchedModule.setText(patchedModules.iterator().next().fModule);
+ }
+
+ private IPackageFragmentRoot[] findRoots(CPListElement element) {
+ IClasspathEntry entry= element.getClasspathEntry();
+ IPackageFragmentRoot[] roots= element.getJavaProject().findPackageFragmentRoots(entry);
+ if (roots.length == 0) {
+ // 2nd attempt in case "module=true" is not explicit on the real cp entry:
+ entry= copyCPEntryWithoutModuleAttribute(entry);
+ if (entry != null)
+ roots= element.getJavaProject().findPackageFragmentRoots(entry);
+ }
+ return roots;
+ }
+
+ private IClasspathEntry copyCPEntryWithoutModuleAttribute(IClasspathEntry entry) {
+ IClasspathAttribute[] oldAttributes= entry.getExtraAttributes();
+ IClasspathAttribute[] newAttributes= new IClasspathAttribute[oldAttributes.length];
+ int count= 0;
+ for (int i= 0; i < oldAttributes.length; i++) {
+ if (!oldAttributes[i].getName().equals(IClasspathAttribute.MODULE))
+ newAttributes[count++]= oldAttributes[i];
+ }
+ if (count == oldAttributes.length)
+ return null;
+ newAttributes= count == 0 ? new IClasspathAttribute[0] : Arrays.copyOf(newAttributes, count);
+ return JavaCore.newContainerEntry(entry.getPath(), entry.getAccessRules(), newAttributes, entry.isExported());
+ }
+
+ private Set<String> moduleNames() {
+ if (fModuleNames != null)
+ return fModuleNames;
+ Set<String> moduleNames= new HashSet<>();
+ if (fJavaElements != null) {
+ for (int i= 0; i < fJavaElements.length; i++) {
+ if (fJavaElements[i] instanceof IPackageFragmentRoot) {
+ IModuleDescription module= ((IPackageFragmentRoot) fJavaElements[i]).getModuleDescription();
+ if (module != null) {
+ recordModule(module, moduleNames);
+ }
+ } else if (fJavaElements[i] instanceof IJavaProject) {
+ try {
+ IModuleDescription module= ((IJavaProject) fJavaElements[i]).getModuleDescription();
+ if (module != null) {
+ recordModule(module, moduleNames);
+ }
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ }
+ }
+ }
+ return fModuleNames= moduleNames;
+ }
+
+ private void recordModule(IModuleDescription module, Set<String> moduleNames) {
+ String moduleName= module.getElementName();
+ if (moduleNames.add(moduleName)) {
+ try {
+ for (String required : JavaModelAccess.getRequiredModules(module)) {
+ List<String> requiredModules= fModule2RequiredModules.get(moduleName);
+ if (requiredModules == null) {
+ requiredModules= new ArrayList<>();
+ fModule2RequiredModules.put(moduleName, requiredModules);
+ }
+ requiredModules.add(required);
+ }
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
}
}
}
- private void addEntry(ListDialogField<ModuleAddExport> field) {
- ModuleAddExport initialValue= new ModuleAddExport(getSourceModuleName(), NO_NAME, getCurrentModuleName(), null);
- ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, initialValue);
- if (dialog.open() == Window.OK) {
- ModuleAddExport export= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
- if (export != null)
- field.addElement(export);
+ private void updateImplicitlyIncluded() {
+ List<String> implicitNames= fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames;
+ fModuleLists[IDX_AVAILABLE].fNames.addAll(implicitNames);
+ implicitNames.clear();
+ for (String explicitName : fModuleLists[IDX_INCLUDED].fNames) {
+ if (!implicitNames.contains(explicitName)) {
+ collectRequired(explicitName);
+ }
+ }
+ }
+
+ private void collectRequired(String explicitName) {
+ List<String> requireds= fModule2RequiredModules.get(explicitName);
+ if (requireds == null) {
+ return;
+ }
+ List<String> implicitNames= fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames;
+ for (String required : requireds) {
+ if (!fModuleLists[IDX_INCLUDED].fNames.contains(required)) {
+ if (!implicitNames.contains(required)) {
+ if (fModuleLists[IDX_AVAILABLE].fNames.remove(required)) {
+ implicitNames.add(required);
+ collectRequired(required);
+ }
+ }
+ }
}
}
@@ -367,46 +831,117 @@ public class ModuleDialog extends StatusDialog {
// -------- TypeRestrictionAdapter --------
- private class AddExportsAdapter implements IListAdapter<ModuleAddExport>, IDialogFieldListener {
+ private abstract class ListAdapter<T extends ModuleEncapsulationDetail> implements IListAdapter<T> {
/**
* @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#customButtonPressed(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField, int)
*/
@Override
- public void customButtonPressed(ListDialogField<ModuleAddExport> field, int index) {
- doCustomButtonPressed(field, index);
+ public void customButtonPressed(ListDialogField<T> field, int index) {
+ if (index == IDX_ADD) {
+ addEntry(field);
+ } else if (index == IDX_EDIT) {
+ doubleClicked(field);
+ }
}
/**
* @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#selectionChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField)
*/
@Override
- public void selectionChanged(ListDialogField<ModuleAddExport> field) {
+ public void selectionChanged(ListDialogField<T> field) {
doSelectionChanged(field);
}
/**
* @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#doubleClicked(org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField)
*/
@Override
- public void doubleClicked(ListDialogField<ModuleAddExport> field) {
- doDoubleClicked(field);
+ public void doubleClicked(ListDialogField<T> field) {
+ List<T> selElements= field.getSelectedElements();
+ if (selElements.size() != 1) {
+ return;
+ }
+ editEntry(field, selElements.get(0));
+ }
+
+ abstract void addEntry(ListDialogField<T> field);
+
+ abstract void editEntry(ListDialogField<T> field, T detail);
+ }
+
+ private class AddExportsAdapter extends ListAdapter<ModuleAddExport> {
+
+ @Override
+ void addEntry(ListDialogField<ModuleAddExport> field) {
+ ModuleAddExport initialValue= new ModuleAddExport(getSourceModuleName(), NO_NAME, getCurrentModuleName(), null);
+ ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, initialValue);
+ if (dialog.open() == Window.OK) {
+ ModuleAddExport export= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
+ if (export != null)
+ field.addElement(export);
+ }
}
- /**
- * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener#dialogFieldChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField)
- */
@Override
- public void dialogFieldChanged(DialogField field) {
- if (field == fIsModuleCheckbox) {
- doSelectionChanged(fAddExportsList);
+ void editEntry(ListDialogField<ModuleAddExport> field, ModuleAddExport export) {
+ ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(getShell(), fJavaElements, export);
+ if (dialog.open() == Window.OK) {
+ ModuleAddExport newExport= dialog.getExport(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
+ if (newExport != null) {
+ field.replaceElement(export, newExport);
+ } else {
+ field.removeElement(export);
+ }
+ }
+ }
+ }
+
+ private class AddReadsAdapter extends ListAdapter<ModuleAddReads> {
+
+ @Override
+ void addEntry(ListDialogField<ModuleAddReads> field) {
+ ModuleAddReads initialValue= new ModuleAddReads(getSourceModuleName(), NO_NAME, null);
+ ModuleAddReadsDialog dialog= new ModuleAddReadsDialog(getShell(), fJavaElements, initialValue);
+ if (dialog.open() == Window.OK) {
+ ModuleAddReads reads= dialog.getReads(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
+ if (reads != null)
+ field.addElement(reads);
+ }
+ }
+
+ @Override
+ void editEntry(ListDialogField<ModuleAddReads> field, ModuleAddReads reads) {
+ ModuleAddReadsDialog dialog= new ModuleAddReadsDialog(getShell(), fJavaElements, reads);
+ if (dialog.open() == Window.OK) {
+ ModuleAddReads newReads= dialog.getReads(fCurrCPElement.findAttributeElement(CPListElement.MODULE));
+ if (newReads != null) {
+ field.replaceElement(reads, newReads);
+ } else {
+ field.removeElement(reads);
+ }
}
}
}
- public ModuleAddExport[] getAddExports() {
+ /**
+ * When the dialog is closed, this method provides the results.
+ * @return an array of ModuleEncapsulationDetail encoding the result of editing
+ */
+ public ModuleEncapsulationDetail[] getAllDetails() {
if (!fIsModuleCheckbox.isSelected())
return null;
- List<ModuleAddExport> elements= fAddExportsList.getElements();
- return elements.toArray(new ModuleAddExport[elements.size()]);
+ CPListElementAttribute attribute= fCurrCPElement.findAttributeElement(CPListElement.MODULE);
+ List<ModuleEncapsulationDetail> allElements= new ArrayList<>();
+ allElements.addAll(fAddExportsList.getElements());
+ allElements.addAll(fAddReadsList.getElements());
+ if (fIsPatchCheckbox.isSelected()) {
+ String patchedModule= fPatchedModule.getText().trim();
+ if (!patchedModule.isEmpty())
+ allElements.add(ModulePatch.fromString(attribute, patchedModule));
+ }
+ if (!fModuleLists[IDX_AVAILABLE].fNames.isEmpty() || !fModuleLists[IDX_IMPLICITLY_INCLUDED].fNames.isEmpty()) {
+ allElements.add(new ModuleEncapsulationDetail.LimitModules(fModuleLists[IDX_INCLUDED].fNames, attribute));
+ }
+ return allElements.toArray(new ModuleEncapsulationDetail[allElements.size()]);
}
/*
@@ -422,4 +957,8 @@ public class ModuleDialog extends StatusDialog {
helpContextId= IJavaHelpContextIds.ACCESS_RULES_DIALOG; // FIXME
PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, helpContextId);
}
+
+ public static StatusInfo newSilentError() {
+ return new StatusInfo(IStatus.ERROR, Util.ZERO_LENGTH_STRING);
+ }
}
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
new file mode 100644
index 0000000000..17df0239b5
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ModuleEncapsulationDetail.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2017 GK Software AG, and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.ui.wizards.buildpaths;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.runtime.IPath;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+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;
+
+/**
+ * Node in the tree of CPListElement et al, representing a module directive like add-exports ...
+ */
+public abstract class ModuleEncapsulationDetail {
+
+ protected CPListElementAttribute fAttribElem;
+
+ public CPListElementAttribute getParent() {
+ return fAttribElem;
+ }
+
+ /**
+ * Retrieve the java element(s) targeted by a given classpath entry.
+ * @param currentProject the Java project holding the classpath entry
+ * @param path the path value of the classpath entry
+ * @return either an array of {@link IPackageFragmentRoot} or a singleton array of {@link IJavaProject}
+ * targeted by the given classpath entry, or {@code null} if no not found
+ */
+ public static IJavaElement[] getTargetJavaElements(IJavaProject currentProject, IPath path) {
+ IResource member= ResourcesPlugin.getWorkspace().getRoot().findMember(path);
+ if (member != null) {
+ IJavaElement element= JavaCore.create(member);
+ if (element != null)
+ return new IJavaElement[] {element};
+ } else if (path != null && path.isAbsolute()) {
+ try {
+ for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) {
+ if (classpathEntry.getPath().equals(path)) {
+ switch (classpathEntry.getEntryKind()) {
+ case IClasspathEntry.CPE_LIBRARY:
+ return new IJavaElement[] {currentProject.getPackageFragmentRoot(path.toString())};
+ default:
+ // keep looking
+ }
+ }
+ }
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ } else {
+ try {
+ for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) {
+ if (classpathEntry.getPath().equals(path)) {
+ return JavaModelAccess.getUnfilteredPackageFragmentRoots(currentProject, classpathEntry);
+ }
+ }
+ } catch (JavaModelException e) {
+ JavaPlugin.log(e);
+ }
+ }
+ return null;
+ }
+
+ public static String encodeFiltered(ModuleEncapsulationDetail[] details, Class<?> detailClass) {
+ return Arrays.stream(details)
+ .filter(detailClass::isInstance)
+ .map(ModuleEncapsulationDetail::toString)
+ .collect(Collectors.joining(":")); //$NON-NLS-1$
+ }
+
+ /**
+ * Node in the tree of CPListElement et al, representing a patch-module directive.
+ */
+ static class ModulePatch extends ModuleEncapsulationDetail {
+
+ public static ModulePatch fromString(CPListElementAttribute attribElem, String value) {
+ return new ModulePatch(value, attribElem);
+ }
+
+ public final String fModule;
+
+ public ModulePatch(String module, CPListElementAttribute attribElem) {
+ fModule= module;
+ fAttribElem= attribElem;
+ }
+
+ @Override
+ public String toString() {
+ return fModule;
+ }
+ }
+
+ /**
+ * Node in the tree of CPListElement et al, representing an add-exports module directive.
+ */
+ static class ModuleAddExport extends ModuleEncapsulationDetail {
+
+ public static ModuleAddExport fromString(CPListElementAttribute attribElem, String value) {
+ int slash= value.indexOf('/');
+ int equals= value.indexOf('=');
+ if (slash != -1 && equals != -1 && equals > slash) {
+ return new ModuleAddExport(value.substring(0, slash),
+ value.substring(slash+1, equals),
+ value.substring(equals+1),
+ attribElem);
+ }
+ return null;
+ }
+
+ public static Collection<ModuleAddExport> fromMultiString(CPListElementAttribute attribElem, String values) {
+ List<ModuleAddExport> exports= new ArrayList<>();
+ for (String value : values.split(":")) { //$NON-NLS-1$
+ ModuleAddExport export= fromString(attribElem, value);
+ if (export != null)
+ exports.add(export);
+ }
+ return exports;
+ }
+
+ public final String fSourceModule;
+ public final String fPackage;
+ public final String fTargetModules;
+
+ public ModuleAddExport(String sourceModule, String aPackage, String targetModules, CPListElementAttribute attribElem) {
+ fSourceModule= sourceModule;
+ fPackage= aPackage;
+ fTargetModules= targetModules;
+ fAttribElem= attribElem;
+ }
+
+ @Override
+ public String toString() {
+ return fSourceModule+'/'+fPackage+'='+fTargetModules;
+ }
+ }
+
+ /**
+ * Node in the tree of CPListElement et al, representing an add-reads module directive.
+ */
+ static class ModuleAddReads extends ModuleEncapsulationDetail {
+
+ public static ModuleAddReads fromString(CPListElementAttribute attribElem, String value) {
+ int equals= value.indexOf('=');
+ if (equals != -1) {
+ return new ModuleAddReads(value.substring(0, equals),
+ value.substring(equals+1),
+ attribElem);
+ }
+ return null;
+ }
+
+ public static Collection<ModuleAddReads> fromMultiString(CPListElementAttribute attribElem, String values) {
+ List<ModuleAddReads> readss= new ArrayList<>();
+ for (String value : values.split(":")) { //$NON-NLS-1$
+ ModuleAddReads reads= fromString(attribElem, value);
+ if (reads != null)
+ readss.add(reads);
+ }
+ return readss;
+ }
+
+ public final String fSourceModule;
+ public final String fTargetModule;
+
+ public ModuleAddReads(String sourceModule, String targetModule, CPListElementAttribute attribElem) {
+ fSourceModule= sourceModule;
+ fTargetModule= targetModule;
+ fAttribElem= attribElem;
+ }
+
+ @Override
+ public String toString() {
+ return fSourceModule+'='+fTargetModule;
+ }
+ }
+
+ /**
+ * Node in the tree of CPListElement et al, representing a limit-modules directive.
+ */
+ static class LimitModules extends ModuleEncapsulationDetail {
+
+ public static LimitModules fromString(CPListElementAttribute attribElem, String value) {
+ String[] modules= value.split(","); //$NON-NLS-1$
+ for (int i= 0; i < modules.length; i++) {
+ modules[i]= modules[i].trim();
+ }
+ return new LimitModules(Arrays.asList(modules), attribElem);
+ }
+
+ public final List<String> fExplicitlyIncludedModules;
+
+ public LimitModules(List<String> explicitlyIncludedModules, CPListElementAttribute attribElem) {
+ fExplicitlyIncludedModules= explicitlyIncludedModules;
+ fAttribElem= attribElem;
+ }
+ @Override
+ public String toString() {
+ return String.join(",", fExplicitlyIncludedModules); //$NON-NLS-1$
+ }
+ }
+}
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 8fbe31617c..1e199d066e 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
@@ -189,13 +189,13 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
private void updateClasspathList() {
List<CPListElement> projelements= fProjectsList.getElements();
- List<CPListElement> flattenedProjElements = new ArrayList<CPListElement>();
+ List<CPListElement> flattenedProjElements = new ArrayList<>();
for ( int i =0; i < projelements.size(); i++ ) {
CPListElement ele = projelements.get(i);
// if root node, collect the CPList elements
if(ele.isRootNodeForPath()) {
ArrayList<Object> children= ele.getChildren();
- for (Iterator iterator= children.iterator(); iterator.hasNext();) {
+ for (Iterator<?> iterator= children.iterator(); iterator.hasNext();) {
Object object= iterator.next();
if(object instanceof CPListElement) {
flattenedProjElements.add((CPListElement) object);
@@ -336,7 +336,7 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
for (CPListElement cpListElement : elementsToAdd) {
Object attribute= cpListElement.getAttribute(IClasspathAttribute.MODULE);
if(attribute == null) {
- cpListElement.setAttribute(IClasspathAttribute.MODULE, new ModuleAddExport[0]);
+ cpListElement.setAttribute(IClasspathAttribute.MODULE, new ModuleEncapsulationDetail[0]);
}
}
@@ -372,8 +372,8 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
removeCustomAttribute(attrib);
}
selElements.remove(i);
- } else if (elem instanceof ModuleAddExport) {
- removeAddExport((ModuleAddExport) elem);
+ } else if (elem instanceof ModuleEncapsulationDetail) {
+ removeEncapsulationDetail((ModuleEncapsulationDetail) elem);
}
}
if (selElements.isEmpty()) {
@@ -424,7 +424,7 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
return false;
}
}
- } else if (elem instanceof ModuleAddExport) {
+ } else if (elem instanceof ModuleEncapsulationDetail) {
return true;
} else if (elem instanceof CPListElement) {
if (((CPListElement)elem).isRootNodeForPath()) {
@@ -488,7 +488,7 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
if (key.equals(CPListElement.ACCESSRULES)) {
showAccessRestrictionDialog(elem.getParent());
} else if (key.equals(CPListElement.MODULE)) {
- needRefresh= showAddExportDialog(getShell(), elem);
+ needRefresh= showModuleDialog(getShell(), elem);
} else {
needRefresh= editCustomAttribute(getShell(), elem);
}
@@ -558,7 +558,7 @@ public class ProjectsWorkbookPage extends BuildPathBasePage {
CPListElement curr= elements.get(i);
if (curr.isRootNodeForPath()) {
ArrayList<Object> children= curr.getChildren();
- for (Iterator iterator= children.iterator(); iterator.hasNext();) {
+ for (Iterator<?> iterator= children.iterator(); iterator.hasNext();) {
Object object= iterator.next();
if(object instanceof CPListElement) {
CPListElement cpe = (CPListElement)object;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/ISharedImages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/ISharedImages.java
index a8d37a6826..bfe37848a5 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/ISharedImages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/ISharedImages.java
@@ -1,14 +1,10 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
- * This is an implementation of an early-draft specification developed under the Java
- * Community Process (JCP) and is made available for testing and evaluation purposes
- * only. The code is not compatible with any specification of the JCP.
- *
* Contributors:
* IBM Corporation - initial API and implementation
* Frits Jalvingh - Contribution for Bug 459831 - [launching] Support attaching external annotations to a JRE container
@@ -305,12 +301,6 @@ public interface ISharedImages {
public static final String IMG_OBJS_EXTERNAL_ANNOTATIONS = JavaPluginImages.IMG_OBJS_EXTERNAL_ANNOTATIONS;
/**
- * Key to access the shared image or image descriptor for an add-exports module directive.
- * @since 3.13 BETA_JAVA9
- */
- public static final String IMG_OBJS_ADD_EXPORTS = JavaPluginImages.IMG_OBJS_ADD_EXPORTS;
-
- /**
* Returns the shared image managed under the given key.
* <p>
* Note that clients <b>must not</b> dispose the image returned by this method.
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/BuildPathDialogAccess.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/BuildPathDialogAccess.java
index cc8a6cb2b4..bf209467b1 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/BuildPathDialogAccess.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/BuildPathDialogAccess.java
@@ -43,7 +43,6 @@ import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
@@ -63,8 +62,6 @@ import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathContainerWizard;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.EditVariableEntryDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ExternalAnnotationsAttachmentDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.JavadocLocationDialog;
-import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleAddExport;
-import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleAddExportsDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.MultipleFolderSelectionDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.NewVariableEntryDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceAttachmentDialog;
@@ -167,25 +164,6 @@ public final class BuildPathDialogAccess {
}
/**
- * Shows the UI for configuring an add-exports classpath attribute. <code>null</code> is
- * returned when the user cancels the dialog. The dialog does not apply any changes.
- *
- * @param shell The parent shell for the dialog
- * @param sourceElements the Java elements representing the source modules from which more packages should be exported
- * @param initialValue The export value to edit; format: {@code <source-module>/<package>=<target-module>(,<target-module>)*}.
- * @return Returns the entered value, possibly different from the initialValue,
- * or <code>null</code> if the dialog has been cancelled.
- * @since 3.13 BETA_JAVA9
- */
- public static String configureAddExports(Shell shell, IJavaElement[] sourceElements, String initialValue) {
- ModuleAddExportsDialog dialog= new ModuleAddExportsDialog(shell, sourceElements, ModuleAddExport.fromString(null, initialValue));
- if (dialog.open() == Window.OK) {
- return dialog.getResult();
- }
- return null;
- }
-
- /**
* Shows the UI for configuring a javadoc location. <code>null</code> is returned
* if the user cancels the dialog. If OK is pressed, an array of length 1 containing the configured URL is
* returned. Note that the configured URL can be <code>null</code> when the user

Back to the top