Skip to content

Show Open/Close Project for mixed selections in Project Explorer#3866

Open
vogella wants to merge 2 commits intoeclipse-platform:masterfrom
vogella:fix/issue-3790-open-close-mixed-selection
Open

Show Open/Close Project for mixed selections in Project Explorer#3866
vogella wants to merge 2 commits intoeclipse-platform:masterfrom
vogella:fix/issue-3790-open-close-mixed-selection

Conversation

@vogella
Copy link
Copy Markdown
Contributor

@vogella vogella commented Apr 5, 2026

The ResourceMgmtActionProvider enablement expression required all selected elements to adapt to IResource or IWorkingSet. This hid Open/Close Project actions when the selection contained non-resource elements (e.g., working set headers from Ctrl+A).

Changed the enablement to always activate the provider (using <or/>, the same pattern as UndoRedoActionProvider). The existing fillContextMenu() logic via selectionToProjects() already filters to applicable projects and only shows relevant actions — no behavioral change for pure-project selections.

Fixes #3790

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 5, 2026

Test Results

   852 files  ±0     852 suites  ±0   55m 21s ⏱️ -38s
 7 902 tests +3   7 659 ✅ +3  243 💤 ±0  0 ❌ ±0 
20 208 runs  +9  19 553 ✅ +9  655 💤 ±0  0 ❌ ±0 

Results for commit ea62040. ± Comparison against base commit dceb45a.

♻️ This comment has been updated with latest results.

@vogella vogella force-pushed the fix/issue-3790-open-close-mixed-selection branch 4 times, most recently from 05018be to e1e0229 Compare April 13, 2026 18:49
@vogella vogella marked this pull request as ready for review April 15, 2026 23:09
@vogella vogella force-pushed the fix/issue-3790-open-close-mixed-selection branch 2 times, most recently from 7252610 to 424a16a Compare April 18, 2026 19:27
@vogella vogella requested a review from Copilot April 20, 2026 14:01
vogella added 2 commits April 20, 2026 16:01
Ctrl+A in an expanded Project Explorer produces a mixed selection:
projects, child files/folders, and non-adaptable elements such as
working set headers. Three problems combined to hide the Open/Close
Project actions in that case:

1. The ResourceMgmtActionProvider enablement expression required ALL
   selected elements to adapt to IResource or IWorkingSet, so the
   provider was never activated for mixed selections. Fixed by replacing
   the expression with <or/> to always activate the provider.

2. CloseResourceAction and OpenResourceAction.updateSelection() called
   selectionIsOfType(PROJECT), which returns false whenever any
   non-IResource element (e.g. a working set header) is present in the
   selection, even if every resource element is a valid open/closed
   project. Fixed by checking getSelectedResources() directly.

3. CloseUnrelatedProjectsAction.resourceChanged() had the same
   selectionIsOfType guard, preventing the action from reacting to
   project state changes for mixed selections. Fixed analogously.

ResourceMgmtActionProvider now overrides getSelectedResources() on the
open/close action instances to filter the selection down to IProject
elements only, so that files and folders selected alongside projects
(expanded Ctrl+A) do not disable the actions.

Fixes eclipse-platform#3790
Move the project-filtering logic from anonymous getSelectedResources()
overrides in ResourceMgmtActionProvider into the action classes
themselves (OpenResourceAction, CloseResourceAction,
CloseUnrelatedProjectsAction). This fixes the API analysis build
failure caused by illegally subclassing these action classes.

The updateSelection() methods now filter getSelectedResources() to
IProject instances, so mixed selections (e.g. Ctrl+A) correctly
enable/disable Open/Close Project actions. The resourceChanged()
methods also use stream-based project checks instead of
selectionIsOfType() to react properly to project state changes
during mixed selections.
@vogella vogella force-pushed the fix/issue-3790-open-close-mixed-selection branch from 424a16a to ea62040 Compare April 20, 2026 14:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets Project Explorer context-menu behavior so that Open/Close Project-related actions remain visible for mixed selections (e.g., when Ctrl+A includes working set headers or other non-resource elements), aligning with the behavior requested in issue #3790.

Changes:

  • Made ResourceMgmtActionProvider enablement unconditional in plugin.xml so the provider is invoked even for mixed/non-resource selections.
  • Added navigator tests covering mixed selections (projects + files, projects + non-adaptable objects, multiple open projects with child resources).
  • Updated project open/close actions’ selection checks to be based on “any selected project” (stream filter) instead of selectionIsOfType(PROJECT).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/org.eclipse.ui.tests.navigator/src/org/eclipse/ui/tests/navigator/resources/ResourceMgmtActionProviderTests.java Adds regression coverage for mixed selections and helper methods to build arbitrary selections.
bundles/org.eclipse.ui.navigator.resources/plugin.xml Changes action provider enablement to always-on (<or/>) to avoid being filtered out by mixed selections.
bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/OpenResourceAction.java Adjusts enablement and delta-check gating to detect projects in mixed selections.
bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseUnrelatedProjectsAction.java Adjusts delta-check gating to detect projects in mixed selections.
bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java Adjusts enablement and delta-check gating to detect projects in mixed selections.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +231 to 235
List<IProject> projects = getSelectedResources().stream()
.filter(IProject.class::isInstance).map(IProject.class::cast).toList();
if (projects.isEmpty()) {
return false;
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateSelection() now enables the action when any project is selected, even in mixed selections. However, run()/runInBackground() still uses getSelectedResources() and then casts every element to IProject (e.g., when building scheduling rules), which will throw ClassCastException if the selection includes non-project resources (files/folders) as allowed by the new enablement. Filter to IProject consistently (ideally by overriding getActionResources() to return only projects and using that list throughout run()).

Copilot uses AI. Check for mistakes.
Comment on lines +307 to +309
List<IProject> projects = getSelectedResources().stream()
.filter(IProject.class::isInstance).map(IProject.class::cast).toList();
if (projects.isEmpty()) {
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing mixed selections means internal logic must also tolerate non-project resources. hasOtherClosedProjects() still iterates getSelectedResources() and blindly casts each entry to IProject, which can now be an IFile/IFolder and will cause a ClassCastException when opening projects with references from a mixed selection. Update this logic to only consider selected IProject instances (similar to the new projects filtering in updateSelection()).

Copilot uses AI. Check for mistakes.
Object nonResource = new Object();
ResourceMgmtActionProvider provider = providerForObjects(openProj, nonResource);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(false, true, false, true, true);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regression test covers visibility for a mixed selection that includes a non-adaptable element, but it doesn't assert enablement. Given the goal of issue #3790, it would be valuable to also assert that Close Project / Close Unrelated Projects are enabled (not just present) when an open project is part of the selection; otherwise the menu items could still be shown but unusable.

Suggested change
checkMenuHasCorrectContributions(false, true, false, true, true);
checkMenuHasCorrectContributions(false, true, false, true, true);
assertTrue(isMenuContributionEnabled("org.eclipse.ui.CloseResourceAction"),
"Close Project should be enabled when an open project is selected with a non-adaptable element");
assertTrue(isMenuContributionEnabled("org.eclipse.ui.CloseUnrelatedProjectsAction"),
"Close Unrelated Projects should be enabled when an open project is selected with a non-adaptable element");

Copilot uses AI. Check for mistakes.
Comment on lines +240 to +241
<!-- Always enabled: fillContextMenu() filters to applicable projects -->
<or/>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching the provider enablement to unconditional () makes these actions show up for selections containing non-resource elements, but the underlying actions still need to ignore non-resource selection entries for enablement and execution (not just menu population). Please double-check that the actions added by ResourceMgmtActionProvider are enabled and runnable when the selection includes non-IResource/IWorkingSet elements (e.g., working set headers), otherwise this can regress into visible-but-disabled actions.

Suggested change
<!-- Always enabled: fillContextMenu() filters to applicable projects -->
<or/>
<or>
<adapt type="org.eclipse.core.resources.IResource"/>
<instanceof value="org.eclipse.ui.IWorkingSet"/>
</or>

Copilot uses AI. Check for mistakes.
Comment on lines 262 to 266
public void resourceChanged(IResourceChangeEvent event) {
// don't bother looking at delta if selection not applicable
if (selectionIsOfType(IResource.PROJECT)) {
List<? extends IResource> selectedResources = super.getSelectedResources();
if (selectedResources.stream().anyMatch(IProject.class::isInstance)) {
IResourceDelta delta = event.getDelta();
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CloseUnrelatedProjectsAction is now enabled for mixed selections via provider changes, but updateSelection() still depends on selectionIsOfType(IResource.PROJECT), which returns false when the selection contains any non-resource element (e.g., working set headers). That means this action can still appear but be disabled for the exact scenario in issue #3790. Consider aligning enablement logic with Open/CloseResourceAction (e.g., enable when any selected resource is a project, ignoring non-resources).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Open/Close Project visibility in Project Explorer for mixed selections

2 participants