Skip to content

Commit 0461de2

Browse files
committed
QuickAccessDialog: defer built-in provider construction until first use
Wrap the nine built-in providers in a LazyQuickAccessProvider that exposes the id and requiresUiAccess flag as static metadata and resolves the delegate only on the first getElements/findElement call, so closing the dialog without typing skips constructing them entirely. Marginally helps stabilize QuickAccessDialogTest.testPreviousChoicesAvailableForExtension on Windows by reducing constructor work and the resulting initial-layout resize events that can preempt the compute job.
1 parent 6c53fec commit 0461de2

2 files changed

Lines changed: 116 additions & 11 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Vogella GmbH and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
12+
package org.eclipse.ui.internal.quickaccess;
13+
14+
import java.util.function.Supplier;
15+
import org.eclipse.core.runtime.IProgressMonitor;
16+
import org.eclipse.jface.resource.ImageDescriptor;
17+
import org.eclipse.ui.quickaccess.QuickAccessElement;
18+
19+
/**
20+
* Wraps a {@link QuickAccessProvider} behind a {@link Supplier} so the wrapped
21+
* provider is constructed only when first queried for elements rather than at
22+
* dialog open time. Identity ({@code getId()}) and the
23+
* {@code requiresUiAccess()} flag are answered without forcing instantiation
24+
* so the caller can sort, filter, and route providers by thread without
25+
* triggering lazy construction.
26+
*/
27+
final class LazyQuickAccessProvider extends QuickAccessProvider {
28+
29+
private final String id;
30+
private final boolean requiresUiAccess;
31+
private final Supplier<QuickAccessProvider> supplier;
32+
private volatile QuickAccessProvider delegate;
33+
34+
LazyQuickAccessProvider(String id, boolean requiresUiAccess, Supplier<QuickAccessProvider> supplier) {
35+
this.id = id;
36+
this.requiresUiAccess = requiresUiAccess;
37+
this.supplier = supplier;
38+
}
39+
40+
private QuickAccessProvider delegate() {
41+
QuickAccessProvider d = delegate;
42+
if (d == null) {
43+
synchronized (this) {
44+
d = delegate;
45+
if (d == null) {
46+
d = supplier.get();
47+
delegate = d;
48+
}
49+
}
50+
}
51+
return d;
52+
}
53+
54+
@Override
55+
public String getId() {
56+
return id;
57+
}
58+
59+
@Override
60+
public boolean requiresUiAccess() {
61+
return requiresUiAccess;
62+
}
63+
64+
@Override
65+
public String getName() {
66+
return delegate().getName();
67+
}
68+
69+
@Override
70+
public ImageDescriptor getImageDescriptor() {
71+
return delegate().getImageDescriptor();
72+
}
73+
74+
@Override
75+
public QuickAccessElement[] getElements() {
76+
return delegate().getElements();
77+
}
78+
79+
@Override
80+
public QuickAccessElement[] getElementsSorted(String filter, IProgressMonitor monitor) {
81+
return delegate().getElementsSorted(filter, monitor);
82+
}
83+
84+
@Override
85+
public QuickAccessElement findElement(String id, String filterText) {
86+
return delegate().findElement(id, filterText);
87+
}
88+
89+
@Override
90+
protected void doReset() {
91+
QuickAccessProvider d = delegate;
92+
if (d != null) {
93+
d.reset();
94+
}
95+
}
96+
}

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/quickaccess/QuickAccessDialog.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.eclipse.core.commands.Command;
3232
import org.eclipse.core.runtime.Adapters;
3333
import org.eclipse.core.runtime.Assert;
34+
import org.eclipse.e4.core.contexts.IEclipseContext;
3435
import org.eclipse.e4.ui.model.application.MApplication;
3536
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
3637
import org.eclipse.jface.bindings.TriggerSequence;
@@ -116,20 +117,28 @@ public QuickAccessDialog(IWorkbenchWindow window, Command invokingCommand) {
116117
final MWindow model = workbenchWindow.getModel();
117118

118119
BusyIndicator.showWhile(window.getShell() == null ? null : window.getShell().getDisplay(), () -> {
119-
final CommandProvider commandProvider = new CommandProvider();
120-
commandProvider.setContext(model.getContext().getActiveLeaf());
120+
final IEclipseContext commandContext = model.getContext().getActiveLeaf();
121+
final MApplication application = model.getContext().get(MApplication.class);
121122
List<QuickAccessProvider> providers = new ArrayList<>();
122123
previousPicksProvider = new PreviousPicksProvider(MAXIMUM_NUMBER_OF_ELEMENTS);
123124
previousPicksProvider.setElementsInitializer(() -> restorePreviousEntries(providers));
124125
providers.add(previousPicksProvider);
125-
providers.add(new EditorProvider());
126-
providers.add(new ViewProvider(model.getContext().get(MApplication.class), model));
127-
providers.add(new PerspectiveProvider());
128-
providers.add(commandProvider);
129-
providers.add(new ActionProvider());
130-
providers.add(new WizardProvider());
131-
providers.add(new PreferenceProvider());
132-
providers.add(new PropertiesProvider());
126+
providers.add(new LazyQuickAccessProvider("org.eclipse.ui.editors", true, EditorProvider::new)); //$NON-NLS-1$
127+
providers.add(new LazyQuickAccessProvider("org.eclipse.e4.ui.parts", true, //$NON-NLS-1$
128+
() -> new ViewProvider(application, model)));
129+
providers.add(
130+
new LazyQuickAccessProvider("org.eclipse.ui.perspectives", true, PerspectiveProvider::new)); //$NON-NLS-1$
131+
providers.add(new LazyQuickAccessProvider("org.eclipse.ui.commands", true, () -> { //$NON-NLS-1$
132+
CommandProvider cp = new CommandProvider();
133+
cp.setContext(commandContext);
134+
return cp;
135+
}));
136+
providers.add(new LazyQuickAccessProvider("org.eclipse.ui.actions", true, ActionProvider::new)); //$NON-NLS-1$
137+
providers.add(new LazyQuickAccessProvider("org.eclipse.ui.wizards", false, WizardProvider::new)); //$NON-NLS-1$
138+
providers.add(
139+
new LazyQuickAccessProvider("org.eclipse.ui.preferences", true, PreferenceProvider::new)); //$NON-NLS-1$
140+
providers.add(
141+
new LazyQuickAccessProvider("org.eclipse.ui.properties", true, PropertiesProvider::new)); //$NON-NLS-1$
133142
providers.addAll(QuickAccessExtensionManager.getProviders(() -> {
134143
if (display != null) {
135144
display.asyncExec(() -> {
@@ -139,7 +148,7 @@ public QuickAccessDialog(IWorkbenchWindow window, Command invokingCommand) {
139148
});
140149
}
141150
}));
142-
providers.add(new HelpSearchProvider());
151+
providers.add(new LazyQuickAccessProvider("search.help", false, HelpSearchProvider::new)); //$NON-NLS-1$
143152

144153
Collection<String> previousPickProviderIds = getPreviousPickProviderIds(getDialogSettings());
145154
previousPicksProvider.setInvolvedProviders(

0 commit comments

Comments
 (0)