From cb7f0267f977e94d8d2c94af07ef60591423fe35 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 3 Nov 2017 17:42:47 -0700 Subject: [PATCH] Try to make workspace symbol provider more 'reactive' --- .../META-INF/MANIFEST.MF | 4 +- .../dialogs/InWorkspaceSymbolsProvider.java | 33 +++++++------ .../commons/boot/app/cli/SpringBootApp.java | 46 +++++++++---------- .../util/SimpleWorkspaceService.java | 3 +- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF index 04f7dc0dd..9c95dbb31 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/META-INF/MANIFEST.MF @@ -16,7 +16,9 @@ Require-Bundle: org.eclipse.ui, com.google.guava, org.eclipse.core.jobs, org.eclipse.core.runtime;bundle-version="3.13.0", - org.springsource.ide.eclipse.commons.core;bundle-version="3.9.1" + org.springsource.ide.eclipse.commons.core;bundle-version="3.9.1", + io.projectreactor.reactor-core;bundle-version="3.0.7", + org.reactivestreams.reactive-streams;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Activator: org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin Bundle-ActivationPolicy: lazy 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 f598a6a08..a5b1af758 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 @@ -13,7 +13,7 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs; import java.time.Duration; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.resources.IProject; @@ -31,10 +31,14 @@ 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 InWorkspaceSymbolsProvider implements SymbolsProvider { private static final Duration TIMEOUT = Duration.ofSeconds(2); + private static final int MAX_RESULTS = 200; private List languageServers; @@ -58,19 +62,22 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider { // - 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. + WorkspaceSymbolParams params = new WorkspaceSymbolParams(query); + ImmutableList.Builder allSymbols = ImmutableList.builder(); - for (LanguageServer server : this.languageServers) { - try { - WorkspaceSymbolParams params = new WorkspaceSymbolParams(query); - List symbolsFuture = - server.getWorkspaceService().symbol(params) - .get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); - allSymbols.addAll(symbolsFuture); - } catch (Exception e) { - GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e)); - } - } - return allSymbols.build(); + 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) + ); + //Consider letting the Flux go out from here instead of blocking and collecting elements. + return symbols.take(MAX_RESULTS).collect(Collectors.toList()).block(); + } + + private static void log(Throwable e) { + GotoSymbolPlugin.getInstance().getLog().log(ExceptionUtil.status(e)); } public static InWorkspaceSymbolsProvider createFor(ExecutionEvent event) { diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java index 3a6daeaaa..e97b2f4e1 100644 --- a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java +++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java @@ -65,6 +65,8 @@ public class SpringBootApp { private static final String LOCAL_CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress"; + private Boolean isSpringBootApp; + private final Supplier jmxConnect = Suppliers.memoize(() -> { String address = null; try { @@ -114,33 +116,31 @@ public class SpringBootApp { } public boolean isSpringBootApp() { - return !containsSystemProperty("sts4.languageserver.name") - && ( - isSpringBootAppClasspath() || - isSpringBootAppSysprops() - ); + if (isSpringBootApp==null) { + try { + isSpringBootApp = !containsSystemProperty("sts4.languageserver.name") + && ( + isSpringBootAppClasspath() || + isSpringBootAppSysprops() + ); + } catch (Exception e) { + Log.log(e); + return false; + } + } + return isSpringBootApp; } - private boolean isSpringBootAppSysprops() { - try { - Properties sysprops = this.vm.getSystemProperties(); - return "org.springframework.boot.loader".equals(sysprops.getProperty("java.protocol.handler.pkgs")); - } catch (Exception e) { - Log.log(e); - } - return false; + private boolean isSpringBootAppSysprops() throws IOException { + Properties sysprops = this.vm.getSystemProperties(); + return "org.springframework.boot.loader".equals(sysprops.getProperty("java.protocol.handler.pkgs")); } - private boolean isSpringBootAppClasspath() { - try { - Properties props = this.vm.getSystemProperties(); - String classpath = (String) props.get("java.class.path"); - String[] cpElements = getClasspath(classpath); - return contains(cpElements, "spring-boot"); - } catch (Exception e) { - Log.log(e); - } - return false; + private boolean isSpringBootAppClasspath() throws IOException { + Properties props = this.vm.getSystemProperties(); + String classpath = (String) props.get("java.class.path"); + String[] cpElements = getClasspath(classpath); + return contains(cpElements, "spring-boot"); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleWorkspaceService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleWorkspaceService.java index 9b37b43ff..1a8097e8f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleWorkspaceService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleWorkspaceService.java @@ -50,7 +50,8 @@ public class SimpleWorkspaceService implements WorkspaceService { } return Mono.fromCallable(() -> { server.waitForReconcile(); - return workspaceSymbolHandler.handle(params); + List symbols = workspaceSymbolHandler.handle(params); + return symbols==null ? ImmutableList.of() : symbols; }) .toFuture() .thenApply(l -> (List)l);