From 7424eeb38bf357f347e1d60d623d9c3f0592655b Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Fri, 12 Dec 2025 09:44:33 +0100 Subject: [PATCH 1/3] Refactor: Improve refresh action performance with parallel processing Replaced WorkspaceModifyOperation with IRunnableWithProgress and direct Job usage in RefreshAction and ResourceMgmtActionProvider to enable parallel refreshing of resources and improve performance. --- .../org/eclipse/ui/actions/RefreshAction.java | 54 +++++++++---------- .../actions/ResourceMgmtActionProvider.java | 14 +++-- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java index 94707e8c36d..1462dddddc4 100644 --- a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java +++ b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java @@ -18,6 +18,7 @@ import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -36,6 +37,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; @@ -217,36 +219,33 @@ final public void refreshAll() { @Override final protected IRunnableWithProgress createOperation(final IStatus[] errorStatus) { - ISchedulingRule rule = null; - IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory(); - List actionResources = new ArrayList<>(getActionResources()); if (shouldPerformResourcePruning()) { actionResources = pruneResources(actionResources); } final List resources = actionResources; - Iterator res = resources.iterator(); - while (res.hasNext()) { - rule = MultiRule.combine(rule, factory.refreshRule(res.next())); - } - return new WorkspaceModifyOperation(rule) { + return new IRunnableWithProgress() { @Override - public void execute(IProgressMonitor mon) { - SubMonitor subMonitor = SubMonitor.convert(mon, resources.size()); - MultiStatus errors = null; + public void run(IProgressMonitor mon) { + SubMonitor subMonitor = SubMonitor.convert(mon); subMonitor.setTaskName(getOperationMessage()); - Iterator resourcesEnum = resources.iterator(); - while (resourcesEnum.hasNext()) { + List errors = Collections.synchronizedList(new ArrayList<>()); + resources.parallelStream().forEach(resource -> { try { - IResource resource = resourcesEnum.next(); - refreshResource(resource, subMonitor.split(1)); + refreshResource(resource, null); } catch (CoreException e) { - errors = recordError(errors, e); + errors.add(e.getStatus()); } - } - if (errors != null) { - errorStatus[0] = errors; + }); + + if (!errors.isEmpty()) { + MultiStatus multiStatus = new MultiStatus(IDEWorkbenchPlugin.IDE_WORKBENCH, IStatus.ERROR, + getProblemsMessage(), null); + for (IStatus s : errors) { + multiStatus.merge(s); + } + errorStatus[0] = multiStatus; } } }; @@ -287,18 +286,17 @@ protected void refreshResource(IResource resource, IProgressMonitor monitor) thr public void run() { final IStatus[] errorStatus = new IStatus[1]; errorStatus[0] = Status.OK_STATUS; - final WorkspaceModifyOperation op = (WorkspaceModifyOperation) createOperation(errorStatus); - WorkspaceJob job = new WorkspaceJob("refresh") { //$NON-NLS-1$ + final IRunnableWithProgress op = createOperation(errorStatus); + Job job = new Job("refresh") { //$NON-NLS-1$ @Override - public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + public IStatus run(IProgressMonitor monitor) { try { op.run(monitor); } catch (InvocationTargetException e) { - String msg = NLS.bind( - IDEWorkbenchMessages.WorkspaceAction_logTitle, getClass() - .getName(), e.getTargetException()); - throw new CoreException(StatusUtil.newStatus(IStatus.ERROR, msg, e.getTargetException())); + String msg = NLS.bind(IDEWorkbenchMessages.WorkspaceAction_logTitle, getClass().getName(), + e.getTargetException()); + return StatusUtil.newStatus(IStatus.ERROR, msg, e.getTargetException()); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } @@ -306,10 +304,6 @@ IDEWorkbenchMessages.WorkspaceAction_logTitle, getClass() } }; - ISchedulingRule rule = op.getRule(); - if (rule != null) { - job.setRule(rule); - } job.setUser(true); job.schedule(); } diff --git a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java index 28111551293..9c32d9a8fcf 100644 --- a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java +++ b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java @@ -31,8 +31,10 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; +import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; @@ -218,11 +220,11 @@ protected void makeActions() { public void run() { final IStatus[] errorStatus = new IStatus[1]; errorStatus[0] = Status.OK_STATUS; - final WorkspaceModifyOperation op = (WorkspaceModifyOperation) createOperation(errorStatus); - WorkspaceJob job = new WorkspaceJob("refresh") { //$NON-NLS-1$ + final IRunnableWithProgress op = createOperation(errorStatus); + Job job = new Job("refresh") { //$NON-NLS-1$ @Override - public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + public IStatus run(IProgressMonitor monitor) { try { op.run(monitor); if (shell != null && !shell.isDisposed()) { @@ -236,7 +238,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { } } catch (InvocationTargetException e) { String msg = NLS.bind(WorkbenchNavigatorMessages.ResourceMgmtActionProvider_logTitle, getClass().getName(), e.getTargetException()); - throw new CoreException(new Status(IStatus.ERROR, NavigatorPlugin.PLUGIN_ID, IStatus.ERROR, msg, e.getTargetException())); + return new Status(IStatus.ERROR, NavigatorPlugin.PLUGIN_ID, IStatus.ERROR, msg, e.getTargetException()); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } @@ -244,10 +246,6 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { } }; - ISchedulingRule rule = op.getRule(); - if (rule != null) { - job.setRule(rule); - } job.setUser(true); job.schedule(); } From ecab24c3a044dd3c0f9aeb1f645a777637c5bab8 Mon Sep 17 00:00:00 2001 From: Eclipse Platform Bot Date: Fri, 12 Dec 2025 08:56:11 +0000 Subject: [PATCH 2/3] Version bump(s) for 4.39 stream --- bundles/org.eclipse.ui.ide/META-INF/MANIFEST.MF | 2 +- bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.ui.ide/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.ide/META-INF/MANIFEST.MF index c115a47b5f6..0d2916a41cb 100644 --- a/bundles/org.eclipse.ui.ide/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.ide/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui.ide; singleton:=true -Bundle-Version: 3.22.800.qualifier +Bundle-Version: 3.22.900.qualifier Bundle-Activator: org.eclipse.ui.internal.ide.IDEWorkbenchPlugin Bundle-ActivationPolicy: lazy Bundle-Vendor: %Plugin.providerName diff --git a/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF index 484bfaa8e91..c43a4b1f3a2 100644 --- a/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF @@ -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.900.qualifier +Bundle-Version: 3.9.1000.qualifier Bundle-Activator: org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorPlugin Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin From 02f095d815e5f3a2258aec88aff0f9e1fb51afed Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Wed, 7 Jan 2026 11:38:34 +0100 Subject: [PATCH 3/3] Use WorkspaceModifyOperation with a rule which blocks per project in RefreshAction --- .../org/eclipse/ui/actions/RefreshAction.java | 37 ++++++++++++------- .../actions/ResourceMgmtActionProvider.java | 9 +++-- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java index 1462dddddc4..0d11b04dfaf 100644 --- a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java +++ b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/RefreshAction.java @@ -18,15 +18,12 @@ import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; import java.util.List; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceRuleFactory; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; @@ -37,7 +34,6 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; @@ -51,6 +47,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.ide.IIDEHelpContextIds; import org.eclipse.ui.internal.ide.StatusUtil; import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils; @@ -225,19 +222,30 @@ final protected IRunnableWithProgress createOperation(final IStatus[] errorStatu } final List resources = actionResources; - return new IRunnableWithProgress() { + ISchedulingRule rule = null; + for (IResource resource : resources) { + ISchedulingRule newRule = null; + if (resource.getType() == IResource.ROOT) { + newRule = resource; + } else { + newRule = resource.getProject(); + } + rule = MultiRule.combine(rule, newRule); + } + + return new WorkspaceModifyOperation(rule) { @Override - public void run(IProgressMonitor mon) { - SubMonitor subMonitor = SubMonitor.convert(mon); + public void execute(IProgressMonitor mon) { + SubMonitor subMonitor = SubMonitor.convert(mon, resources.size()); subMonitor.setTaskName(getOperationMessage()); - List errors = Collections.synchronizedList(new ArrayList<>()); - resources.parallelStream().forEach(resource -> { + List errors = new ArrayList<>(); + for (IResource resource : resources) { try { - refreshResource(resource, null); + refreshResource(resource, subMonitor.split(1)); } catch (CoreException e) { errors.add(e.getStatus()); } - }); + } if (!errors.isEmpty()) { MultiStatus multiStatus = new MultiStatus(IDEWorkbenchPlugin.IDE_WORKBENCH, IStatus.ERROR, @@ -287,10 +295,10 @@ public void run() { final IStatus[] errorStatus = new IStatus[1]; errorStatus[0] = Status.OK_STATUS; final IRunnableWithProgress op = createOperation(errorStatus); - Job job = new Job("refresh") { //$NON-NLS-1$ + WorkspaceJob job = new WorkspaceJob("refresh") { //$NON-NLS-1$ @Override - public IStatus run(IProgressMonitor monitor) { + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try { op.run(monitor); } catch (InvocationTargetException e) { @@ -304,6 +312,9 @@ public IStatus run(IProgressMonitor monitor) { } }; + if (op instanceof WorkspaceModifyOperation) { + job.setRule(((WorkspaceModifyOperation) op).getRule()); + } job.setUser(true); job.schedule(); } diff --git a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java index 9c32d9a8fcf..cf226d13595 100644 --- a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java +++ b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/actions/ResourceMgmtActionProvider.java @@ -30,8 +30,6 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.operation.IRunnableWithProgress; @@ -221,10 +219,10 @@ public void run() { final IStatus[] errorStatus = new IStatus[1]; errorStatus[0] = Status.OK_STATUS; final IRunnableWithProgress op = createOperation(errorStatus); - Job job = new Job("refresh") { //$NON-NLS-1$ + WorkspaceJob job = new WorkspaceJob("refresh") { //$NON-NLS-1$ @Override - public IStatus run(IProgressMonitor monitor) { + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try { op.run(monitor); if (shell != null && !shell.isDisposed()) { @@ -246,6 +244,9 @@ public IStatus run(IProgressMonitor monitor) { } }; + if (op instanceof WorkspaceModifyOperation) { + job.setRule(((WorkspaceModifyOperation) op).getRule()); + } job.setUser(true); job.schedule(); }