From 253c514a76b29b81816a48e8c2dbfe3b770b76b6 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 20 May 2020 14:44:28 -0700 Subject: [PATCH] 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 --- .../dialogs/GotoSymbolDialogModel.java | 22 ++++- .../gotosymbol/dialogs/GotoSymbolSection.java | 34 +++++--- .../dialogs/InFileSymbolsProvider.java | 61 ++++++++++---- .../dialogs/InProjectSymbolsProvider.java | 74 +++++++++------- .../dialogs/InWorkspaceSymbolsProvider.java | 2 +- .../handlers/GotoSymbolHandler.java | 9 +- .../gotosymbol/view/SpringSymbolsView.java | 84 ++++++++++++------- .../view/SpringSymbolsViewModel.java | 27 +++++- 8 files changed, 210 insertions(+), 103 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialogModel.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialogModel.java index 6e7d53f65..18293f30b 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialogModel.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialogModel.java @@ -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 { @@ -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 status = new LiveVariable<>(); private int currentSymbolsProviderIndex; - private final LiveVariable currentSymbolsProvider = new LiveVariable<>(null); + public final LiveVariable currentSymbolsProvider = new LiveVariable<>(null); private final LiveVariable searchBox = new LiveVariable<>(""); - private final ObservableSet> unfilteredSymbols = new ObservableSet>(ImmutableSet.of(), AsyncMode.ASYNC, AsyncMode.SYNC) { + public final ObservableSet> unfilteredSymbols = new ObservableSet>(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 diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolSection.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolSection.java index c8860c4e9..f18dfb04a 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolSection.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolSection.java @@ -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; + } + } diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InFileSymbolsProvider.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InFileSymbolsProvider.java index 7caa4dada..e1596ab3c 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InFileSymbolsProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InFileSymbolsProvider.java @@ -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 info; - public InFileSymbolsProvider(LSPDocumentInfo target) { + public InFileSymbolsProvider(Supplier target) { super(); this.info = target; } @Override public List> fetchFor(String query) throws Exception { - DocumentSymbolParams params = new DocumentSymbolParams( - new TextDocumentIdentifier(info.getFileUri().toString())); - CompletableFuture>> symbolsFuture = info.getLanguageClient() - .getTextDocumentService().documentSymbol(params); - List> 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>> symbolsFuture = info.getLanguageClient() + .getTextDocumentService().documentSymbol(params); + List> symbols = symbolsFuture.get(); + return symbols == null ? ImmutableList.of() : ImmutableList.copyOf(symbols); + } + return ImmutableList.of(); + } + + public static SymbolsProvider createFor(LiveExpression rsrc) { + LiveExpression target = rsrc.apply(r -> { + IDocument document = LSPEclipseUtils.getDocument(r); + return getLSPDocumentInfo(document); + }); + return new InFileSymbolsProvider(target::getValue); } public static SymbolsProvider createFor(ITextEditor textEditor) { - Collection 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 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); } diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InProjectSymbolsProvider.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InProjectSymbolsProvider.java index ecf91e43b..3701a7516 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InProjectSymbolsProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InProjectSymbolsProvider.java @@ -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 project) { + LiveExpression> 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 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 languageServers; - private IProject project; + private Supplier> languageServers; + private Supplier project; - public InProjectSymbolsProvider(List languageServers, IProject project) { + public InProjectSymbolsProvider(Supplier> languageServers, Supplier 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> 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> 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)); } - + } diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InWorkspaceSymbolsProvider.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InWorkspaceSymbolsProvider.java index 808ed7308..6ed3545d9 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InWorkspaceSymbolsProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/InWorkspaceSymbolsProvider.java @@ -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)); } - } diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/handlers/GotoSymbolHandler.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/handlers/GotoSymbolHandler.java index fc2d64f6f..2dfec3606 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/handlers/GotoSymbolHandler.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/handlers/GotoSymbolHandler.java @@ -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(); diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsView.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsView.java index 8727e1a23..26bc7cbe6 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsView.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsView.java @@ -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 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 createSections() throws CoreException { List 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; diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsViewModel.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsViewModel.java index a55e65bea..8afe284cf 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsViewModel.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/view/SpringSymbolsViewModel.java @@ -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 currentProject = new LiveVariable<>(); - public final GotoSymbolDialogModel gotoSymbols = new GotoSymbolDialogModel(null, InWorkspaceSymbolsProvider.createFor(currentProject::getValue)); + public final LiveVariable currentResource = new LiveVariable<>(); + public final LiveExpression 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); + } }