From 9039a54b2f8e421192d60b0eb3a6d3cca2f92d08 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Thu, 31 Jan 2019 11:13:55 +0100 Subject: [PATCH] use the new workspace symbol location prefix search capability in symbols in project dialog mode --- .../dialogs/InProjectSymbolsProvider.java | 92 ++++++++++++++----- .../dialogs/InWorkspaceSymbolsProvider.java | 43 ++++----- 2 files changed, 83 insertions(+), 52 deletions(-) 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 bb062a306..708a35484 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 @@ -10,45 +10,38 @@ *******************************************************************************/ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs; +import java.time.Duration; import java.util.List; import java.util.function.Predicate; +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.util.ExceptionUtil; + +import com.google.common.collect.ImmutableList; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @SuppressWarnings("restriction") -public class InProjectSymbolsProvider extends InWorkspaceSymbolsProvider { +public class InProjectSymbolsProvider implements SymbolsProvider { - private final Predicate> FILTER_PREDICATE = e -> { - if(e.isLeft()) { - SymbolInformation symbolInformation = e.getLeft(); - Location location = symbolInformation.getLocation(); - IResource targetResource = LSPEclipseUtils.findResourceFor(location.getUri()); - if (targetResource != null && targetResource.getFullPath() != null) { - return targetResource.getFullPath().toString().startsWith("/" + getProject().getName() + "/"); - } - } - return false; - }; - - public InProjectSymbolsProvider(List languageServers, IProject project) { - super(languageServers, project); - } - - @Override - public String getName() { - return "Symbols in Project"; - } - - public static InWorkspaceSymbolsProvider createFor(ExecutionEvent event) { + 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); @@ -58,9 +51,58 @@ public class InProjectSymbolsProvider extends InWorkspaceSymbolsProvider { return null; } + private static final Duration TIMEOUT = Duration.ofSeconds(2); + private static final int MAX_RESULTS = 200; + + private List languageServers; + private IProject project; + + public InProjectSymbolsProvider(List languageServers, IProject project) { + this.languageServers = languageServers; + this.project = project; + } + @Override - protected Predicate> symbolFilter() { - return FILTER_PREDICATE; + public String getName() { + return "Symbols in Project"; + } + + @Override + public List> fetchFor(String query) throws Exception { + //TODO: if we want decent support for multiple language servers... + // consider changing SymbolsProvider api and turning the stuff in here into something producing a + // Flux> + // This will help in + // - supporting cancelation + // - executing multiple requests to different servers in parallel. + // - producing results per server so don't have to wait for one slow server to see the rest. + //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(); + } + + @Override + public boolean fromFile(SymbolInformation symbol) { + return false; + } + + 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 840fd657f..95529ecb2 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2019 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 @@ -12,7 +12,6 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs; import java.time.Duration; import java.util.List; -import java.util.function.Predicate; import java.util.stream.Collectors; import org.eclipse.core.commands.ExecutionEvent; @@ -31,7 +30,6 @@ import org.eclipse.ui.handlers.HandlerUtil; import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin; import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil; -import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import reactor.core.publisher.Flux; @@ -40,15 +38,23 @@ import reactor.core.publisher.Mono; @SuppressWarnings("restriction") public class InWorkspaceSymbolsProvider implements SymbolsProvider { + public static InWorkspaceSymbolsProvider createFor(IProject project) { + List languageServers = LanguageServiceAccessor.getLanguageServers(project, + capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()), true); + if (!languageServers.isEmpty()) { + return new InWorkspaceSymbolsProvider(languageServers); + } + return null; + } + + private static final Duration TIMEOUT = Duration.ofSeconds(2); private static final int MAX_RESULTS = 200; private List languageServers; - private IProject project; - public InWorkspaceSymbolsProvider(List languageServers, IProject project) { + public InWorkspaceSymbolsProvider(List languageServers) { this.languageServers = languageServers; - this.project = project; } @Override @@ -78,16 +84,12 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider { .map(symbol -> Either.forLeft(symbol)) ); //Consider letting the Flux go out from here instead of blocking and collecting elements. - return symbols.filter(symbolFilter()).take(MAX_RESULTS).collect(Collectors.toList()).block(); - } - - private static void log(Throwable e) { - GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e)); + return symbols.take(MAX_RESULTS).collect(Collectors.toList()).block(); } public static InWorkspaceSymbolsProvider createFor(ExecutionEvent event) { final IProject project = projectFor(event); - if (project!=null) { + if (project != null) { return createFor(project); } return null; @@ -113,26 +115,13 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider { } - public static InWorkspaceSymbolsProvider createFor(IProject project) { - List languageServers = LanguageServiceAccessor.getLanguageServers(project, - capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()), true); - if (!languageServers.isEmpty()) { - return new InWorkspaceSymbolsProvider(languageServers, project); - } - return null; - } - @Override public boolean fromFile(SymbolInformation symbol) { return false; } - protected Predicate> symbolFilter() { - return Predicates.alwaysTrue(); - } - - protected IProject getProject() { - return project; + private static void log(Throwable e) { + GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e)); } }