Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Plugin.name
Bundle-SymbolicName: org.eclipse.ui.navigator.resources; singleton:=true
Bundle-Version: 3.9.500.qualifier
Bundle-Version: 3.9.600.qualifier
Bundle-Activator: org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorPlugin
Bundle-Vendor: %Plugin.providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.ICommand;
Expand Down Expand Up @@ -114,20 +113,16 @@ public void fillActionBars(IActionBars actionBars) {
@Override
public void fillContextMenu(IMenuManager menu) {
IStructuredSelection selection = (IStructuredSelection) getContext().getSelection();
boolean isProjectSelection = true;
boolean hasOpenProjects = false;
boolean hasClosedProjects = false;
boolean hasBuilder = true; // false if any project is closed or does not
// have builder
boolean hasBuilder = true; // false if any project is closed or does not have builder
List<IProject> projects = selectionToProjects(selection);
boolean selectionContainsNonProject = projects.size() < selection.size();

Iterator<IProject> projects = selectionToProjects(selection).iterator();

while (projects.hasNext() && (!hasOpenProjects || !hasClosedProjects || hasBuilder || isProjectSelection)) {
IProject project = projects.next();

if (project == null) {
isProjectSelection = false;
continue;
for (IProject project : projects) {
if (hasOpenProjects && hasClosedProjects && !hasBuilder) {
// we've set all booleans of interest; no need to loop any further
break;
}
if (project.isOpen()) {
hasOpenProjects = true;
Expand All @@ -139,30 +134,29 @@ public void fillContextMenu(IMenuManager menu) {
hasBuilder = false;
}
}
if (!selection.isEmpty() && isProjectSelection && !ResourcesPlugin.getWorkspace().isAutoBuilding()
if (!selection.isEmpty() && !ResourcesPlugin.getWorkspace().isAutoBuilding()
&& hasBuilder) {
// Allow manual incremental build only if auto build is off.
buildAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, buildAction);
}
// Add the 'refresh' item if any selection is either (a) an open project, or (b)
// a non-project selection (so the 'refresh' item is not shown if all selections
// are closed projects)
if (hasOpenProjects || !isProjectSelection) {
// Add the 'refresh' item if ANY selection is either (a) an open project, or (b)
// a non-project selection.
// Put another way: the 'refresh' item is NOT shown if ALL selections are closed
// projects.
if (hasOpenProjects || selectionContainsNonProject) {
refreshAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, refreshAction);
}
if (isProjectSelection) {
if (hasClosedProjects) {
openProjectAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, openProjectAction);
}
if (hasOpenProjects) {
closeProjectAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, closeProjectAction);
closeUnrelatedProjectsAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, closeUnrelatedProjectsAction);
}
if (hasClosedProjects) {
openProjectAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, openProjectAction);
}
if (hasOpenProjects) {
closeProjectAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, closeProjectAction);
closeUnrelatedProjectsAction.selectionChanged(selection);
menu.appendToGroup(ICommonMenuConstants.GROUP_BUILD, closeUnrelatedProjectsAction);
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/org.eclipse.ui.tests.navigator/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %bundlename
Bundle-SymbolicName: org.eclipse.ui.tests.navigator;singleton:=true
Bundle-Version: 3.7.600.qualifier
Bundle-Version: 3.7.700.qualifier
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.resources,
org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.ui.tests.navigator.resources.FoldersAsProjectsContributionTest;
import org.eclipse.ui.tests.navigator.resources.NestedResourcesTests;
import org.eclipse.ui.tests.navigator.resources.PathComparatorTest;
import org.eclipse.ui.tests.navigator.resources.ResourceMgmtActionProviderTests;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
Expand All @@ -34,7 +35,7 @@
ProgrammaticOpenTest.class, PipelineTest.class, PipelineChainTest.class, JstPipelineTest.class,
LabelProviderTest.class, SorterTest.class, ViewerTest.class, CdtTest.class, M12Tests.class,
FirstClassM1Tests.class, LinkHelperTest.class, ShowInTest.class, ResourceTransferTest.class,
EvaluationCacheTest.class,
EvaluationCacheTest.class, ResourceMgmtActionProviderTests.class,
NestedResourcesTests.class, PathComparatorTest.class, FoldersAsProjectsContributionTest.class,
GoBackForwardsTest.class
// DnDTest.class, // DnDTest.testSetDragOperation() fails
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*******************************************************************************
* Copyright (c) 2024 Dave Carpeneto and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.ui.tests.navigator.resources;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.internal.navigator.NavigatorContentService;
import org.eclipse.ui.internal.navigator.extensions.CommonActionExtensionSite;
import org.eclipse.ui.internal.navigator.resources.actions.ResourceMgmtActionProvider;
import org.eclipse.ui.navigator.CommonViewerSiteFactory;
import org.eclipse.ui.navigator.ICommonActionExtensionSite;
import org.eclipse.ui.navigator.ICommonMenuConstants;
import org.eclipse.ui.tests.navigator.NavigatorTestBase;
import org.junit.Before;
import org.junit.Test;

public final class ResourceMgmtActionProviderTests extends NavigatorTestBase {

private IMenuManager manager;

public ResourceMgmtActionProviderTests() {
_navigatorInstanceId = TEST_VIEWER;
}

@Override
@Before
public void setUp() {
super.setUp();
manager = new MenuManager();
manager.add(new GroupMarker(ICommonMenuConstants.GROUP_BUILD));
}

/**
* Test for 'no selection' condition - no menu items should be included
*/
@Test
public void testFillContextMenu_noSelection() {
ResourceMgmtActionProvider provider = provider((IResource[]) null);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(false, false, false, false, false);
}

/**
* Test for 'folder' condition - only 'refresh' should be included
*/
@Test
public void testFillContextMenu_folderSelection() {

IFolder justAFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(new Path("some/folder"));
ResourceMgmtActionProvider provider = provider(justAFolder);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(false, true, false, false, false);
}

/**
* Test for 'closed project' - only 'open project' should be included
*/
@Test
public void testFillContextMenu_closedProjectSelection() {
IProject closedProj = ResourcesPlugin.getWorkspace().getRoot().getProject("closedProj");
ResourceMgmtActionProvider provider = provider(closedProj);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(false, false, true, false, false);
}

/**
* Test for 'open project' that doesn't have a builder attached - all but
* 'build' & 'open project' should be enabled
*/
@Test
public void testFillContextMenu_openProjectNoBuilderSelection() {
IProject openProj = ResourcesPlugin.getWorkspace().getRoot().getProject("Test");
boolean autoBuildInitialState = ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding();

try {
if (!autoBuildInitialState) {
// we want to enable auto-building for this test to guarantee that the 'build'
// menu option isn't shown
IWorkspaceDescription wsd = ResourcesPlugin.getWorkspace().getDescription();
wsd.setAutoBuilding(true);
ResourcesPlugin.getWorkspace().setDescription(wsd);
}
openProj.open(null);
} catch (CoreException e) {
fail(e.getClass().getSimpleName() + " thrown: " + e.getLocalizedMessage());
}
ResourceMgmtActionProvider provider = provider(openProj);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(false, true, false, true, true);

if (!autoBuildInitialState) {
// clean-up: reset autobuild since we changed it
try {
IWorkspaceDescription wsd = ResourcesPlugin.getWorkspace().getDescription();
wsd.setAutoBuilding(false);
ResourcesPlugin.getWorkspace().setDescription(wsd);
} catch (CoreException e) {
fail(e.getClass().getSimpleName() + " thrown: " + e.getLocalizedMessage());
}
}
}

/**
* Test for 'open project' that doesn't have a builder attached - only 'open
* project' should be disabled
*/
@Test
public void testFillContextMenu_openProjectWithBuilderSelection() {
IProject openProj = ResourcesPlugin.getWorkspace().getRoot().getProject("Test");
IWorkspaceDescription wsd = ResourcesPlugin.getWorkspace().getDescription();
boolean autobuildInitialState = wsd.isAutoBuilding();
boolean hasNoInitialBuildCommands = false;
IProjectDescription desc = null;
try {
if (autobuildInitialState) {
wsd.setAutoBuilding(false);
ResourcesPlugin.getWorkspace().setDescription(wsd);
}
openProj.open(null);
desc = openProj.getDescription();
if (desc.getBuildSpec().length == 0) {
hasNoInitialBuildCommands = true;
ICommand cmd = desc.newCommand();
desc.setBuildSpec(new ICommand[] { cmd });
openProj.setDescription(desc, null);
}
} catch (CoreException e) {
fail(e.getClass().getSimpleName() + " thrown: " + e.getLocalizedMessage());
}
ResourceMgmtActionProvider provider = provider(openProj);
provider.fillContextMenu(manager);
checkMenuHasCorrectContributions(true, true, false, true, true);
try {
// clean-up where needed: reset autobuild if we changed it & remove
// the build config if we added it
if (autobuildInitialState) {
wsd.setAutoBuilding(true);
ResourcesPlugin.getWorkspace().setDescription(wsd);
}
if (desc != null && hasNoInitialBuildCommands) {
desc.setBuildSpec(new ICommand[0]);
openProj.setDescription(desc, null);
}
} catch (CoreException e) {
fail(e.getClass().getSimpleName() + " thrown: " + e.getLocalizedMessage());
}
}

/*
* Return a provider, given the selected navigator items
*/
private ResourceMgmtActionProvider provider(IResource... selectedElements) {
ICommonActionExtensionSite cfg = new CommonActionExtensionSite("NA", "NA",
CommonViewerSiteFactory.createCommonViewerSite(_commonNavigator.getViewSite()),
(NavigatorContentService) _contentService, _viewer);
ResourceMgmtActionProvider provider = new ResourceMgmtActionProvider();
StructuredSelection selection = null;
if (selectedElements != null && selectedElements.length > 0) {
selection = new StructuredSelection(selectedElements);
} else {
selection = new StructuredSelection();
}
provider.setContext(new ActionContext(selection));
provider.init(cfg);
return provider;
}

/*
* Check the expected menu items (passed in) against what the menu actually has
*/
private void checkMenuHasCorrectContributions(boolean... actions) {
if (actions.length != 5) { // there's 5 menus we check for
fail(String.format("Incorrect number of menu items being checked : %d", actions.length));
}
int index = 0;
for (String thisAction : new String[] { "org.eclipse.ui.BuildAction", "org.eclipse.ui.RefreshAction",
"org.eclipse.ui.OpenResourceAction", "org.eclipse.ui.CloseResourceAction",
"org.eclipse.ui.CloseUnrelatedProjectsAction" }) {
assertTrue(String.format("Unexpected menu membership for %s (%b)", thisAction, !actions[index]),
actions[index] == menuHasContribution(thisAction));
index++;
}
}

/*
* Check the menu for the named entry
*/
private boolean menuHasContribution(String contribution) {
for (IContributionItem thisItem : manager.getItems()) {
if (thisItem.getId().equals(contribution)) {
return true;
}
}
return false;
}

}
Loading