Add support for 'scopes' to 'Spring Symbols View'

Other polishes/fixes:

- double-click and enter properly opens the symbol location in editor.
- remove status line from Symbols view (it displays info that is
  redundant as it is also shown in the 'scope' field)
- refresh symbols when current resource/project selection changes
This commit is contained in:
Kris De Volder
2020-05-20 14:44:28 -07:00
parent 8d61856584
commit 253c514a76
8 changed files with 210 additions and 103 deletions

View File

@@ -18,9 +18,13 @@ import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.Assert;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin;
import org.springsource.ide.eclipse.commons.core.util.FuzzyMatcher;
import org.springsource.ide.eclipse.commons.core.util.StringUtil;
@@ -34,6 +38,7 @@ import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@SuppressWarnings("restriction")
public class GotoSymbolDialogModel {
public static class Match<T> {
@@ -77,13 +82,22 @@ public class GotoSymbolDialogModel {
}
private static final OKHandler DEFAULT_OK_HANDLER = (selection) -> true;
public static final OKHandler OPEN_IN_EDITOR_OK_HANDLER = symbolInformation -> {
if (symbolInformation!=null) {
Location location = symbolInformation.getLocation();
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
LSPEclipseUtils.openInEditor(location, page);
}
return true;
};
private SymbolsProvider[] symbolsProviders;
private final LiveVariable<HighlightedText> status = new LiveVariable<>();
private int currentSymbolsProviderIndex;
private final LiveVariable<SymbolsProvider> currentSymbolsProvider = new LiveVariable<>(null);
public final LiveVariable<SymbolsProvider> currentSymbolsProvider = new LiveVariable<>(null);
private final LiveVariable<String> searchBox = new LiveVariable<>("");
private final ObservableSet<Either<SymbolInformation, DocumentSymbol>> unfilteredSymbols = new ObservableSet<Either<SymbolInformation, DocumentSymbol>>(ImmutableSet.of(), AsyncMode.ASYNC, AsyncMode.SYNC) {
public final ObservableSet<Either<SymbolInformation, DocumentSymbol>> unfilteredSymbols = new ObservableSet<Either<SymbolInformation, DocumentSymbol>>(ImmutableSet.of(), AsyncMode.ASYNC, AsyncMode.SYNC) {
//Note: fetching is 'slow' so is done asynchronously
{
setRefreshDelay(100);
@@ -206,6 +220,10 @@ public class GotoSymbolDialogModel {
currentSymbolsProviderIndex = (currentSymbolsProviderIndex+1)%symbolsProviders.length;
currentSymbolsProvider.setValue(symbolsProviders[currentSymbolsProviderIndex]);
}
public SymbolsProvider[] getSymbolsProviders() {
return symbolsProviders;
}
/**
* Set an ok handler. The handler is meant to be called by the UI when user request to

View File

@@ -90,7 +90,7 @@ public class GotoSymbolSection extends WizardPageSection {
return null;
}
}
private class GotoSymbolsLabelProvider extends StyledCellLabelProvider {
private Stylers stylers;
@@ -192,7 +192,7 @@ public class GotoSymbolSection extends WizardPageSection {
}
private final GotoSymbolDialogModel model;
private boolean enableStatusLine = true;
public GotoSymbolSection(IPageWithSections owner, GotoSymbolDialogModel model) {
super(owner);
@@ -258,16 +258,19 @@ public class GotoSymbolSection extends WizardPageSection {
installWidgetListeners(pattern, viewer);
//Status label
StyledText statusLabel = new StyledText(dialogArea, SWT.NONE);
// Allow for some extra space for highlight fonts
statusLabel.setLeftMargin(3);
statusLabel.setBottomMargin(2);
statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
if (enableStatusLine) {
StyledText statusLabel = new StyledText(dialogArea, SWT.NONE);
// Allow for some extra space for highlight fonts
statusLabel.setLeftMargin(3);
statusLabel.setBottomMargin(2);
statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Stylers stylers = new Stylers(dialogArea.getFont());
disposables.add(stylers);
SwtConnect.connectHighlighted(stylers.bold(), statusLabel, model.getStatus(), Duration.ofMillis(500));
}
Stylers stylers = new Stylers(dialogArea.getFont());
disposables.add(stylers);
SwtConnect.connectHighlighted(stylers.bold(), statusLabel, model.getStatus(), Duration.ofMillis(500));
viewer.setInput(model);
}
@@ -398,4 +401,13 @@ public class GotoSymbolSection extends WizardPageSection {
return val != null ? Optional.of(val) : Optional.empty();
}
/**
* Enable or disable displaying status line at the bottom of the goto symbols view/section.
*/
public GotoSymbolSection enableStatusLine(boolean enable) {
this.enableStatusLine = enable;
return this;
}
}

View File

@@ -13,7 +13,10 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.LanguageServiceAccessor.LSPDocumentInfo;
@@ -23,6 +26,7 @@ import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.ui.texteditor.ITextEditor;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import com.google.common.collect.ImmutableList;
@@ -34,34 +38,54 @@ import com.google.common.collect.ImmutableList;
@SuppressWarnings("restriction")
public class InFileSymbolsProvider implements SymbolsProvider {
private LSPDocumentInfo info;
private Supplier<LSPDocumentInfo> info;
public InFileSymbolsProvider(LSPDocumentInfo target) {
public InFileSymbolsProvider(Supplier<LSPDocumentInfo> target) {
super();
this.info = target;
}
@Override
public List<Either<SymbolInformation, DocumentSymbol>> fetchFor(String query) throws Exception {
DocumentSymbolParams params = new DocumentSymbolParams(
new TextDocumentIdentifier(info.getFileUri().toString()));
CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> symbolsFuture = info.getLanguageClient()
.getTextDocumentService().documentSymbol(params);
List<Either<SymbolInformation, DocumentSymbol>> symbols = symbolsFuture.get();
return symbols == null ? ImmutableList.of() : ImmutableList.copyOf(symbols);
LSPDocumentInfo info = this.info.get();
if (info!=null) {
DocumentSymbolParams params = new DocumentSymbolParams(
new TextDocumentIdentifier(info.getFileUri().toString()));
CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> symbolsFuture = info.getLanguageClient()
.getTextDocumentService().documentSymbol(params);
List<Either<SymbolInformation, DocumentSymbol>> symbols = symbolsFuture.get();
return symbols == null ? ImmutableList.of() : ImmutableList.copyOf(symbols);
}
return ImmutableList.of();
}
public static SymbolsProvider createFor(LiveExpression<IResource> rsrc) {
LiveExpression<LSPDocumentInfo> target = rsrc.apply(r -> {
IDocument document = LSPEclipseUtils.getDocument(r);
return getLSPDocumentInfo(document);
});
return new InFileSymbolsProvider(target::getValue);
}
public static SymbolsProvider createFor(ITextEditor textEditor) {
Collection<LSPDocumentInfo> infos = LanguageServiceAccessor.getLSPDocumentInfosFor(
LSPEclipseUtils.getDocument(textEditor),
capabilities -> Boolean.TRUE.equals(capabilities.getDocumentSymbolProvider()));
if (infos.isEmpty()) {
return null;
}
// TODO maybe consider better strategy such as iterating on all LS until we have a good result
LSPDocumentInfo info = infos.iterator().next();
IDocument document = LSPEclipseUtils.getDocument(textEditor);
LSPDocumentInfo info = getLSPDocumentInfo(document);
if (info!=null) {
return new InFileSymbolsProvider(info);
return new InFileSymbolsProvider(() -> info);
}
return null;
}
private static LSPDocumentInfo getLSPDocumentInfo(IDocument document) {
if (document!=null) {
Collection<LSPDocumentInfo> infos = LanguageServiceAccessor.getLSPDocumentInfosFor(
document,
capabilities -> Boolean.TRUE.equals(capabilities.getDocumentSymbolProvider()));
if (infos.isEmpty()) {
return null;
}
// TODO maybe consider better strategy such as iterating on all LS until we have a good result
return infos.iterator().next();
}
return null;
}
@@ -73,7 +97,8 @@ public class InFileSymbolsProvider implements SymbolsProvider {
@Override
public boolean fromFile(SymbolInformation symbol) {
if (symbol != null && symbol.getLocation() != null) {
LSPDocumentInfo info = this.info.get();
if (info!=null && symbol != null && symbol.getLocation() != null) {
String symbolUri = symbol.getLocation().getUri();
return info.getFileUri().toString().equals(symbolUri);
}

View File

@@ -12,25 +12,20 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
import java.time.Duration;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil;
import com.google.common.collect.ImmutableList;
@@ -41,27 +36,38 @@ import reactor.core.publisher.Mono;
@SuppressWarnings("restriction")
public class InProjectSymbolsProvider implements SymbolsProvider {
public static InProjectSymbolsProvider createFor(LiveExpression<IProject> project) {
LiveExpression<List<LanguageServer>> languageServers = project.apply(p ->
p == null
? ImmutableList.of()
: LanguageServiceAccessor.getLanguageServers(
project.getValue(),
capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()),
true
)
);
return new InProjectSymbolsProvider(languageServers::getValue, project::getValue);
}
public static InProjectSymbolsProvider createFor(ExecutionEvent event) {
final IProject project = InWorkspaceSymbolsProvider.projectFor(event);
final List<LanguageServer> languageServers = LanguageServiceAccessor.getLanguageServers(project,
capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()), true);
if (!languageServers.isEmpty()) {
return new InProjectSymbolsProvider(languageServers, project);
if (project!=null) {
return createFor(LiveExpression.constant(project));
}
return null;
}
private static final Duration TIMEOUT = Duration.ofSeconds(2);
private static final int MAX_RESULTS = 200;
private List<LanguageServer> languageServers;
private IProject project;
private Supplier<List<LanguageServer>> languageServers;
private Supplier<IProject> project;
public InProjectSymbolsProvider(List<LanguageServer> languageServers, IProject project) {
public InProjectSymbolsProvider(Supplier<List<LanguageServer>> languageServers, Supplier<IProject> project) {
this.languageServers = languageServers;
this.project = project;
}
@Override
public String getName() {
return "Symbols in Project";
@@ -79,21 +85,25 @@ public class InProjectSymbolsProvider implements SymbolsProvider {
//However it will also add complexity to the code that consumes this and at this time we only
// really use this with a single language server anyways.
String projectLocationPrefix = LSPEclipseUtils.toUri(project).toString();
query = "locationPrefix:" + projectLocationPrefix + "?" + query;
WorkspaceSymbolParams params = new WorkspaceSymbolParams(query);
Flux<Either<SymbolInformation, DocumentSymbol>> symbols = Flux.fromIterable(this.languageServers)
.flatMap(server -> Mono.fromFuture(server.getWorkspaceService().symbol(params))
.timeout(TIMEOUT)
.doOnError(e -> log(e))
.onErrorReturn(ImmutableList.of())
.flatMapMany(Flux::fromIterable)
.map(symbol -> Either.forLeft(symbol))
);
//Consider letting the Flux go out from here instead of blocking and collecting elements.
return symbols.take(MAX_RESULTS).collect(Collectors.toList()).block();
IProject project = this.project.get();
if (project!=null) {
String projectLocationPrefix = LSPEclipseUtils.toUri(project).toString();
query = "locationPrefix:" + projectLocationPrefix + "?" + query;
WorkspaceSymbolParams params = new WorkspaceSymbolParams(query);
Flux<Either<SymbolInformation, DocumentSymbol>> symbols = Flux.fromIterable(this.languageServers.get())
.flatMap(server -> Mono.fromFuture(server.getWorkspaceService().symbol(params))
.timeout(TIMEOUT)
.doOnError(e -> log(e))
.onErrorReturn(ImmutableList.of())
.flatMapMany(Flux::fromIterable)
.map(symbol -> Either.forLeft(symbol))
);
//Consider letting the Flux go out from here instead of blocking and collecting elements.
return symbols.take(MAX_RESULTS).collect(Collectors.toList()).block();
}
return ImmutableList.of();
}
@Override
@@ -104,5 +114,5 @@ public class InProjectSymbolsProvider implements SymbolsProvider {
private static void log(Throwable e) {
GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e));
}
}

View File

@@ -29,6 +29,7 @@ import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin;
import org.springsource.ide.eclipse.commons.livexp.ui.Ilabelable;
import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil;
import com.google.common.collect.ImmutableList;
@@ -134,5 +135,4 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider {
private static void log(Throwable e) {
GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e));
}
}

View File

@@ -66,14 +66,7 @@ public class GotoSymbolHandler extends AbstractHandler {
final ITextEditor textEditor = (ITextEditor) part;
GotoSymbolDialogModel model = new GotoSymbolDialogModel(getKeybindings(event), InWorkspaceSymbolsProvider.createFor(event), InProjectSymbolsProvider.createFor(event), InFileSymbolsProvider.createFor(textEditor))
.setOkHandler(symbolInformation -> {
if (symbolInformation!=null) {
Location location = symbolInformation.getLocation();
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
LSPEclipseUtils.openInEditor(location, page);
}
return true;
});
.setOkHandler(GotoSymbolDialogModel.OPEN_IN_EDITOR_OK_HANDLER);
GotoSymbolDialog dialog = new GotoSymbolDialog(shell, textEditor, model, /*alignRight*/ false);
currentDialog = model;
dialog.open();

View File

@@ -1,9 +1,18 @@
/*******************************************************************************
* Copyright (c) 2020 Pivotal, Inc.
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.gotosymbol.view;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
@@ -12,23 +21,31 @@ import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4j.Location;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.springframework.ide.eclipse.boot.dash.views.sections.ViewPartWithSections;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolSection;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
import org.springsource.ide.eclipse.commons.livexp.ui.DescriptionSection;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InFileSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InProjectSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InWorkspaceSymbolsProvider;
import org.springsource.ide.eclipse.commons.livexp.ui.ChooseOneSectionCombo;
import org.springsource.ide.eclipse.commons.livexp.ui.IPageSection;
import org.springsource.ide.eclipse.commons.livexp.ui.InfoFieldSection;
import org.springsource.ide.eclipse.commons.livexp.ui.StringFieldSection;
import org.springsource.ide.eclipse.commons.livexp.ui.SimpleLabelProvider;
import org.springsource.ide.eclipse.commons.livexp.util.Log;
import com.google.common.collect.ImmutableList;
@SuppressWarnings("restriction")
public class SpringSymbolsView extends ViewPartWithSections {
/**
@@ -38,11 +55,10 @@ public class SpringSymbolsView extends ViewPartWithSections {
private static final boolean ENABLE_SCROLLING = false;
private final SpringSymbolsViewModel model = new SpringSymbolsViewModel();
private final LiveExpression<String> projectAsString = model.currentProject.apply(p -> {
System.out.println("project = "+p);
return p==null ? "null" : p.getName();
});
{
model.gotoSymbols.setOkHandler(GotoSymbolDialogModel.OPEN_IN_EDITOR_OK_HANDLER);
}
private ISelectionListener selectionListener = new ISelectionListener() {
@@ -51,9 +67,9 @@ public class SpringSymbolsView extends ViewPartWithSections {
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object element = ss.getFirstElement();
IProject project = getProject(element);
if (project!=null) {
model.currentProject.setValue(project);
IResource rsrc = getResource(element);
if (rsrc!=null) {
model.currentResource.setValue(rsrc);
}
} else if (selection instanceof ITextSelection) {
//Let's assume the selection is in the active editor
@@ -61,13 +77,7 @@ public class SpringSymbolsView extends ViewPartWithSections {
IEditorPart editor = getSite().getWorkbenchWindow().getActivePage().getActiveEditor();
if (editor!=null) {
IEditorInput input = editor.getEditorInput();
IResource resource = input.getAdapter(IResource.class);
if (resource != null) {
IProject project = resource.getProject();
if (project!=null) {
model.currentProject.setValue(project);
}
}
model.currentResource.setValue(input.getAdapter(IResource.class));
}
} catch (Exception e) {
Log.log(e);
@@ -75,14 +85,11 @@ public class SpringSymbolsView extends ViewPartWithSections {
}
}
private IProject getProject(Object element) {
private IResource getResource(Object element) {
if (element instanceof IResource) {
return ((IResource) element).getProject();
return (IResource) element;
} else if (element instanceof IAdaptable) {
IResource resource = ((IAdaptable) element).getAdapter(IResource.class);
if (resource!=null) {
return resource.getProject();
}
return ((IAdaptable) element).getAdapter(IResource.class);
}
return null;
}
@@ -92,11 +99,30 @@ public class SpringSymbolsView extends ViewPartWithSections {
super(ENABLE_SCROLLING);
}
@SuppressWarnings("resource")
@Override
protected List<IPageSection> createSections() throws CoreException {
List<IPageSection> sections = new ArrayList<>();
sections.add(new InfoFieldSection(this, "Project", projectAsString));
sections.add(new GotoSymbolSection(this, model.gotoSymbols));
sections.add(
new ChooseOneSectionCombo<>(this, "Scope",
model.gotoSymbols.currentSymbolsProvider,
ImmutableList.copyOf(model.gotoSymbols.getSymbolsProviders())
)
.setLabelProvider(new SimpleLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof InWorkspaceSymbolsProvider) {
return "Workspace";
} else if (element instanceof InProjectSymbolsProvider) {
return "Project";
} else if (element instanceof InFileSymbolsProvider) {
return "File";
}
return super.getText(element);
}
})
);
sections.add(new GotoSymbolSection(this, model.gotoSymbols).enableStatusLine(false));
ISelectionService selectitonService = getSite().getWorkbenchWindow().getSelectionService();
selectitonService.addSelectionListener(selectionListener);
return sections;

View File

@@ -1,13 +1,36 @@
/*******************************************************************************
* Copyright (c) 2020 Pivotal, Inc.
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.gotosymbol.view;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InFileSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InProjectSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InWorkspaceSymbolsProvider;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
public class SpringSymbolsViewModel {
public final LiveVariable<IProject> currentProject = new LiveVariable<>();
public final GotoSymbolDialogModel gotoSymbols = new GotoSymbolDialogModel(null, InWorkspaceSymbolsProvider.createFor(currentProject::getValue));
public final LiveVariable<IResource> currentResource = new LiveVariable<>();
public final LiveExpression<IProject> currentProject = currentResource.apply(r -> r==null ? null : r.getProject());
public final GotoSymbolDialogModel gotoSymbols = new GotoSymbolDialogModel(null,
InWorkspaceSymbolsProvider.createFor(currentProject::getValue),
InProjectSymbolsProvider.createFor(currentProject),
InFileSymbolsProvider.createFor(currentResource)
);
{
gotoSymbols.unfilteredSymbols.dependsOn(currentProject);
}
}