From 328607f531caaf59590e8ddb16bb455c43025033 Mon Sep 17 00:00:00 2001 From: nsingh Date: Mon, 12 Mar 2018 16:07:43 -0700 Subject: [PATCH] Streamline async handler API Added an async handler for LS requests that should not run on the same thread as LSP4J event loop. Also streamlined method signatures for handlers and removed useless CompletableFuture. --- .../completion/VscodeCompletionEngine.java | 10 +-- .../VscodeCompletionEngineAdapter.java | 11 ++- .../CompositeLanguageServerComponents.java | 2 +- .../definition/SimpleDefinitionFinder.java | 8 +- .../hover/VscodeHoverEngineAdapter.java | 6 +- .../languageserver/util/AsyncRunner.java | 61 ++++++++++++++++ .../languageserver/util/CodeLensHandler.java | 5 +- .../util/CodeLensResolveHandler.java | 6 +- .../util/CompletionHandler.java | 8 +- .../util/CompletionResolveHandler.java | 6 +- .../util/DefinitionHandler.java | 5 +- .../languageserver/util/HoverHandler.java | 6 +- .../util/ReferencesHandler.java | 5 +- .../util/SimpleLanguageServer.java | 5 ++ .../util/SimpleTextDocumentService.java | 73 +++++++++++-------- .../util/SimpleWorkspaceService.java | 19 +++-- .../commons/maven/java/MavenJavaProject.java | 9 +-- .../commons/maven/java/MavenProjectCache.java | 8 -- .../maven/java/MavenProjectClasspath.java | 7 +- .../vscode/commons/maven/HtmlJavadocTest.java | 2 +- .../vscode/commons/maven/JavaIndexTest.java | 2 +- .../commons/util/RunnableWithException.java | 17 +++++ .../testharness/LanguageServerHarness.java | 15 ++-- .../concourse/ConcourseLanguageServer.java | 7 +- .../ls/extension/ResolveClasspathHandler.java | 2 +- .../ls/extension/ResolveProjectHandler.java | 4 +- .../java/handlers/BootJavaCodeLensEngine.java | 8 +- .../java/handlers/BootJavaHoverProvider.java | 4 +- .../handlers/BootJavaReferencesHandler.java | 8 +- .../boot/java/handlers/ReferenceProvider.java | 3 +- .../ValuePropertyReferencesProvider.java | 8 +- .../vscode/boot/jdt/ls/JdtLsProjectCache.java | 5 +- .../test/PropertyReferenceFinderTest.java | 25 +++---- .../utils/test/CompilationUnitCacheTest.java | 1 + .../utils/test/VSCodeSourceLinksTest.java | 2 +- .../project/harness/ProjectsHarness.java | 2 +- .../{classpath-service.ts => classpath.ts} | 0 .../commons-vscode/src/launch-util.ts | 9 ++- .../src/{project-service.ts => project.ts} | 4 +- 39 files changed, 229 insertions(+), 159 deletions(-) create mode 100644 headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/AsyncRunner.java create mode 100644 headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/RunnableWithException.java rename vscode-extensions/commons-vscode/src/{classpath-service.ts => classpath.ts} (100%) rename vscode-extensions/commons-vscode/src/{project-service.ts => project.ts} (84%) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngine.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngine.java index 199087701..4cab9e905 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngine.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngine.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2018 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 @@ -11,17 +11,17 @@ package org.springframework.ide.vscode.commons.languageserver.completion; -import java.util.concurrent.CompletableFuture; - import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.CompletionList; import org.eclipse.lsp4j.TextDocumentPositionParams; +import reactor.core.publisher.Mono; + /** * Interface that needs to be implemented by a 'completion engine' which can be easily * wired-up to provide completions for a Vscode language server. */ public interface VscodeCompletionEngine { - CompletableFuture getCompletions(TextDocumentPositionParams params); - CompletableFuture resolveCompletion(CompletionItem unresolved); + Mono getCompletions(TextDocumentPositionParams params); + CompletionItem resolveCompletion(CompletionItem unresolved); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java index acca5dabf..94c03f255 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2018 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 @@ -16,7 +16,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import org.eclipse.lsp4j.CompletionItem; @@ -115,8 +114,8 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { } @Override - public CompletableFuture getCompletions(TextDocumentPositionParams params) { - return getCompletionsMono(params).toFuture(); + public Mono getCompletions(TextDocumentPositionParams params) { + return getCompletionsMono(params); } private Mono getCompletionsMono(TextDocumentPositionParams params) { @@ -248,8 +247,8 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { } @Override - public CompletableFuture resolveCompletion(CompletionItem unresolved) { + public CompletionItem resolveCompletion(CompletionItem unresolved) { resolver.resolveNow(unresolved); - return CompletableFuture.completedFuture(unresolved); + return unresolved; } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java index bbcdb9cf2..43cdc5a9f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java @@ -99,7 +99,7 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen //Create composite hover handler this.hoverHandler = new HoverHandler() { @Override - public CompletableFuture handle(TextDocumentPositionParams params) { + public Hover handle(TextDocumentPositionParams params) { TextDocument doc = server.getTextDocumentService().get(params); LanguageId language = doc.getLanguageId(); LanguageServerComponents subComponents = componentsByLanguageId.get(language); diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/definition/SimpleDefinitionFinder.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/definition/SimpleDefinitionFinder.java index 7de697520..ec0eb88fa 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/definition/SimpleDefinitionFinder.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/definition/SimpleDefinitionFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.commons.languageserver.definition; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import org.eclipse.lsp4j.Location; @@ -36,10 +35,9 @@ public class SimpleDefinitionFinder implements D } @Override - public CompletableFuture> handle(TextDocumentPositionParams position) { + public List handle(TextDocumentPositionParams position) { return findDefinitions(position) - .collect(Collectors.toList()) - .toFuture(); + .collect(Collectors.toList()).block(); } /** diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/VscodeHoverEngineAdapter.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/VscodeHoverEngineAdapter.java index 5d7dad2f1..c538ba588 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/VscodeHoverEngineAdapter.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/VscodeHoverEngineAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 2018 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 @@ -59,7 +59,7 @@ public class VscodeHoverEngineAdapter implements HoverHandler { } @Override - public CompletableFuture handle(TextDocumentPositionParams params) { + public Hover handle(TextDocumentPositionParams params) { //TODO: This returns a CompletableFuture which suggests we should try to do expensive work asyncly. // We are currently just doing all this in a blocking way and wrapping the already computed list into // a trivial pre-resolved future. @@ -78,7 +78,7 @@ public class VscodeHoverEngineAdapter implements HoverHandler { String rendered = render(hoverInfo, type); if (StringUtil.hasText(rendered)) { Hover hover = new Hover(ImmutableList.of(Either.forLeft(rendered)), range); - return CompletableFuture.completedFuture(hover); + return hover; } } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/AsyncRunner.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/AsyncRunner.java new file mode 100644 index 000000000..6a90a4359 --- /dev/null +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/AsyncRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2018 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.languageserver.util; + +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; + +import org.springframework.ide.vscode.commons.util.RunnableWithException; + +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +public class AsyncRunner { + + private static Scheduler executor = Schedulers.newSingle("STS4 Thread"); + + // Only need to remember the last request as requests are executed in order, if + // the last request is done, all requests are done + private CompletableFuture lastRequest; + + public AsyncRunner() { + } + + public synchronized CompletableFuture invoke(Callable callable) { + CompletableFuture x = Mono.fromCallable(callable).subscribeOn(executor).toFuture(); + lastRequest = x; + return x; + } + + public synchronized CompletableFuture execute(RunnableWithException runnable) { + CompletableFuture x = Mono.fromCallable(() -> { + runnable.run(); + return (Void) null; + }).subscribeOn(executor).toFuture(); + lastRequest = x; + return x; + } + + public synchronized void waitForAll() { + while (lastRequest != null) { + try { + lastRequest.get(); + } catch (Exception e) { + + } + if (lastRequest.isDone()) { + lastRequest = null; + } + } + } + +} diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensHandler.java index d7eca6ecf..a6977f63a 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.commons.languageserver.util; import java.util.List; -import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.CodeLens; import org.eclipse.lsp4j.CodeLensParams; @@ -19,6 +18,6 @@ import org.eclipse.lsp4j.CodeLensParams; @FunctionalInterface public interface CodeLensHandler { - CompletableFuture> handle(CodeLensParams params); + List handle(CodeLensParams params); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensResolveHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensResolveHandler.java index 4c8ce90e7..23db27db4 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensResolveHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CodeLensResolveHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -10,11 +10,9 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.languageserver.util; -import java.util.concurrent.CompletableFuture; - import org.eclipse.lsp4j.CodeLens; @FunctionalInterface public interface CodeLensResolveHandler { - CompletableFuture handle(CodeLens unresolved); + CodeLens handle(CodeLens unresolved); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionHandler.java index 2fe67b66e..5d4763de3 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2018 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 @@ -11,12 +11,12 @@ package org.springframework.ide.vscode.commons.languageserver.util; -import java.util.concurrent.CompletableFuture; - import org.eclipse.lsp4j.CompletionList; import org.eclipse.lsp4j.TextDocumentPositionParams; +import reactor.core.publisher.Mono; + @FunctionalInterface public interface CompletionHandler { - CompletableFuture handle(TextDocumentPositionParams params); + Mono handle(TextDocumentPositionParams params); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionResolveHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionResolveHandler.java index d84dd7c05..92572837e 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionResolveHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/CompletionResolveHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2018 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 @@ -11,11 +11,9 @@ package org.springframework.ide.vscode.commons.languageserver.util; -import java.util.concurrent.CompletableFuture; - import org.eclipse.lsp4j.CompletionItem; @FunctionalInterface public interface CompletionResolveHandler { - CompletableFuture handle(CompletionItem unresolved); + CompletionItem handle(CompletionItem unresolved) throws Exception; } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DefinitionHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DefinitionHandler.java index 927eef4eb..f55676b2f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DefinitionHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DefinitionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -11,12 +11,11 @@ package org.springframework.ide.vscode.commons.languageserver.util; import java.util.List; -import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.TextDocumentPositionParams; @FunctionalInterface public interface DefinitionHandler { - CompletableFuture> handle(TextDocumentPositionParams position); + List handle(TextDocumentPositionParams position); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/HoverHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/HoverHandler.java index f0f7388c8..6be22f2b9 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/HoverHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/HoverHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2018 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 @@ -11,12 +11,10 @@ package org.springframework.ide.vscode.commons.languageserver.util; -import java.util.concurrent.CompletableFuture; - import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.TextDocumentPositionParams; @FunctionalInterface public interface HoverHandler { - CompletableFuture handle(TextDocumentPositionParams params); + Hover handle(TextDocumentPositionParams params); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ReferencesHandler.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ReferencesHandler.java index da0f0ef60..cbcdfdecd 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ReferencesHandler.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/ReferencesHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 2018 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 @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.commons.languageserver.util; import java.util.List; -import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.ReferenceParams; @@ -19,6 +18,6 @@ import org.eclipse.lsp4j.ReferenceParams; @FunctionalInterface public interface ReferencesHandler { - CompletableFuture> handle(ReferenceParams params); + List handle(ReferenceParams params); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index d770b1800..5a0f53609 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -128,6 +128,8 @@ public class SimpleLanguageServer implements Sts4LanguageServer, LanguageClientA private Runnable shutdownHandler; + private AsyncRunner async = new AsyncRunner(); + @Override public void connect(LanguageClient _client) { this.client = (STS4LanguageClient) _client; @@ -614,4 +616,7 @@ public class SimpleLanguageServer implements Sts4LanguageServer, LanguageClientA this.shutdownHandler = handler; } + public AsyncRunner getAsync() { + return this.async; + } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java index 3b59c53c1..e8e3936c3 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 Pivotal, Inc. + * Copyright (c) 2016, 2018 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 @@ -56,15 +56,13 @@ import org.eclipse.lsp4j.services.TextDocumentService; import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix; import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.CollectorUtil; import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.text.LanguageId; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - public class SimpleTextDocumentService implements TextDocumentService { final private SimpleLanguageServer server; @@ -84,9 +82,11 @@ public class SimpleTextDocumentService implements TextDocumentService { private CodeLensResolveHandler codeLensResolveHandler; private Consumer documentSaveListener; + private AsyncRunner async; public SimpleTextDocumentService(SimpleLanguageServer server) { this.server = server; + this.async = server.getAsync(); } public synchronized void onHover(HoverHandler h) { @@ -141,6 +141,7 @@ public class SimpleTextDocumentService implements TextDocumentService { @Override public final void didChange(DidChangeTextDocumentParams params) { + async.execute(() -> { try { VersionedTextDocumentIdentifier docId = params.getTextDocument(); String url = docId.getUri(); @@ -154,10 +155,12 @@ public class SimpleTextDocumentService implements TextDocumentService { } catch (BadLocationException e) { Log.log(e); } + }); } @Override public void didOpen(DidOpenTextDocumentParams params) { + async.execute(() -> { TextDocumentItem docId = params.getTextDocument(); String url = docId.getUri(); //Log.info("didOpen: "+params.getTextDocument().getUri()); @@ -187,10 +190,12 @@ public class SimpleTextDocumentService implements TextDocumentService { TextDocumentContentChange evt = new TextDocumentContentChange(doc, ImmutableList.of(change)); documentChangeListeners.fire(evt); } + }); } @Override public void didClose(DidCloseTextDocumentParams params) { + async.execute(() -> { //Log.info("didClose: "+params.getTextDocument().getUri()); String url = params.getTextDocument().getUri(); if (url!=null) { @@ -211,6 +216,7 @@ public class SimpleTextDocumentService implements TextDocumentService { Log.warn("Document closed, but it didn't exist! Close event ignored"); } } + }); } void didChangeContent(TextDocument doc, List changes) { @@ -250,37 +256,42 @@ public class SimpleTextDocumentService implements TextDocumentService { } public final static CompletionList NO_COMPLETIONS = new CompletionList(false, Collections.emptyList()); - public final static CompletableFuture NO_HOVER = CompletableFuture.completedFuture(new Hover(ImmutableList.of(), null)); - public final static CompletableFuture> NO_REFERENCES = CompletableFuture.completedFuture(ImmutableList.of()); + public final static Hover NO_HOVER = new Hover(ImmutableList.of(), null); + public final static List NO_REFERENCES = ImmutableList.of(); public final static List NO_SYMBOLS = ImmutableList.of(); - public final static CompletableFuture> NO_CODELENS = CompletableFuture.completedFuture(ImmutableList.of()); + public final static List NO_CODELENS = ImmutableList.of(); @Override public CompletableFuture, CompletionList>> completion(TextDocumentPositionParams position) { CompletionHandler h = completionHandler; if (h!=null) { return completionHandler.handle(position) - .thenApply(Either::forRight); + .map(Either::, CompletionList>forRight) + .toFuture(); } return CompletableFuture.completedFuture(Either.forRight(NO_COMPLETIONS)); } @Override public CompletableFuture resolveCompletionItem(CompletionItem unresolved) { + return async.invoke(() -> { CompletionResolveHandler h = completionResolveHandler; if (h!=null) { return h.handle(unresolved); } return null; + }); } @Override public CompletableFuture hover(TextDocumentPositionParams position) { + return async.invoke(() -> { HoverHandler h = hoverHandler; if (h!=null) { return hoverHandler.handle(position); } - return CompletableFuture.completedFuture(null); + return null; + }); } @Override @@ -288,62 +299,62 @@ public class SimpleTextDocumentService implements TextDocumentService { return CompletableFuture.completedFuture(null); } - @SuppressWarnings({ "unchecked"}) @Override public CompletableFuture> definition(TextDocumentPositionParams position) { + return async.invoke(() -> { DefinitionHandler h = this.definitionHandler; if (h!=null) { - Object r = h.handle(position); //YUCK! - return (CompletableFuture>) r; + return h.handle(position); } - return CompletableFuture.completedFuture(Collections.emptyList()); + return Collections.emptyList(); + }); } @Override public CompletableFuture> references(ReferenceParams params) { + return async.invoke(() -> { ReferencesHandler h = this.referencesHandler; if (h != null) { return h.handle(params); } - return CompletableFuture.completedFuture(Collections.emptyList()); + return Collections.emptyList(); + }); } @Override public CompletableFuture> documentSymbol(DocumentSymbolParams params) { + return async.invoke(() -> { DocumentSymbolHandler documentSymbolHandler = this.documentSymbolHandler; if (documentSymbolHandler==null) { - return CompletableFuture.completedFuture(ImmutableList.of()); + return ImmutableList.of(); } - return Mono.fromCallable(() -> { - server.waitForReconcile(); - List r = documentSymbolHandler.handle(params); - //handle it when symbolHandler is sloppy and returns null instead of empty list. - return r == null ? ImmutableList.of() : r; - }) - .toFuture() - .thenApply(l -> (List)l); + server.waitForReconcile(); + List r = documentSymbolHandler.handle(params); + //handle it when symbolHandler is sloppy and returns null instead of empty list. + return r == null ? ImmutableList.of() : r; + }); } @Override public CompletableFuture> codeAction(CodeActionParams params) { + return async.invoke(() -> { TrackedDocument doc = documents.get(params.getTextDocument().getUri()); if (doc!=null) { - return Flux.fromIterable(doc.getQuickfixes()) + return doc.getQuickfixes().stream() .filter((fix) -> fix.appliesTo(params.getRange(), params.getContext())) .map(Quickfix::getCodeAction) - .collectList() - .toFuture() - .thenApply(l -> (List) l); + .collect(CollectorUtil.toImmutableList()); } else { - return CompletableFuture.completedFuture(ImmutableList.of()); + return ImmutableList.of(); } + }); } @Override public CompletableFuture> codeLens(CodeLensParams params) { CodeLensHandler handler = this.codeLensHandler; if (handler != null) { - return handler.handle(params); + return async.invoke(() -> handler.handle(params)); } return CompletableFuture.completedFuture(Collections.emptyList()); } @@ -352,7 +363,7 @@ public class SimpleTextDocumentService implements TextDocumentService { public CompletableFuture resolveCodeLens(CodeLens unresolved) { CodeLensResolveHandler handler = this.codeLensResolveHandler; if (handler != null) { - return handler.handle(unresolved); + return async.invoke(() -> handler.handle(unresolved)); } return CompletableFuture.completedFuture(null); } @@ -385,6 +396,7 @@ public class SimpleTextDocumentService implements TextDocumentService { // which extends the YEdit editor. This YEdit editor has a problem, where on save, all error markers are deleted. // When STS uses the LSP4E editor and no longer needs its own YEdit-based editor, the issue with error markers disappearing // on save should not be a problem anymore, and the workaround below will no longer be needed. + async.execute(() -> { if (documentSaveListener != null) { TextDocumentIdentifier docId = params.getTextDocument(); String url = docId.getUri(); @@ -394,6 +406,7 @@ public class SimpleTextDocumentService implements TextDocumentService { documentSaveListener.accept(new TextDocumentSaveChange(doc)); } } + }); } public void publishDiagnostics(TextDocumentIdentifier docId, Collection diagnostics) { 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 5391fdf01..401a7744e 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 @@ -34,8 +34,6 @@ import org.springframework.ide.vscode.commons.util.Log; import com.google.common.collect.ImmutableList; -import reactor.core.publisher.Mono; - public class SimpleWorkspaceService implements WorkspaceService { private static Logger log = LoggerFactory.getLogger(SimpleWorkspaceService.class); @@ -50,24 +48,25 @@ public class SimpleWorkspaceService implements WorkspaceService { private ListenerList workspaceFolderListeners = new ListenerList<>(); + private AsyncRunner async; + public SimpleWorkspaceService(SimpleLanguageServer server) { this.server = server; + this.async = server.getAsync(); this.fileObserver = new SimpleServerFileObserver(server); } @Override public CompletableFuture> symbol(WorkspaceSymbolParams params) { + return async.invoke(() -> { WorkspaceSymbolHandler workspaceSymbolHandler = this.workspaceSymbolHandler; if (workspaceSymbolHandler==null) { - return CompletableFuture.completedFuture(ImmutableList.of()); + return ImmutableList.of(); } - return Mono.fromCallable(() -> { - server.waitForReconcile(); - List symbols = workspaceSymbolHandler.handle(params); - return symbols==null ? ImmutableList.of() : symbols; - }) - .toFuture() - .thenApply(l -> (List)l); + server.waitForReconcile(); + List symbols = workspaceSymbolHandler.handle(params); + return symbols == null ? ImmutableList.of() : symbols; + }); } @Override diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java index ca73949d5..ccad4991b 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java @@ -16,7 +16,6 @@ import java.nio.file.Path; import org.springframework.ide.vscode.commons.java.AbstractJavaProject; import org.springframework.ide.vscode.commons.java.ClasspathFileBasedCache; import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath; -import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient; import org.springframework.ide.vscode.commons.maven.MavenCore; import org.springframework.ide.vscode.commons.util.Log; @@ -31,20 +30,20 @@ public class MavenJavaProject extends AbstractJavaProject { private DelegatingCachedClasspath classpath; private File pom; - public MavenJavaProject(STS4LanguageClient client, MavenCore maven, File pom, Path projectDataCache) { + public MavenJavaProject(MavenCore maven, File pom, Path projectDataCache) { super(projectDataCache); this.pom = pom; File file = projectDataCache == null ? null : projectDataCache.resolve(ClasspathFileBasedCache.CLASSPATH_DATA_CACHE_FILE).toFile(); ClasspathFileBasedCache fileBasedCache = new ClasspathFileBasedCache(file); this.classpath = new DelegatingCachedClasspath<>( - () -> new MavenProjectClasspath(client, maven, pom), + () -> new MavenProjectClasspath(maven, pom), fileBasedCache ); } - public MavenJavaProject(STS4LanguageClient client, MavenCore maven, File pom) { - this(client, maven, pom, null); + public MavenJavaProject(MavenCore maven, File pom) { + this(maven, pom, null); if (!classpath.isCached()) { try { classpath.update(); diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java index 28c0cda83..f4c7a0d8e 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java @@ -15,11 +15,9 @@ import java.nio.file.Path; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; -import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.java.AbstractFileToProjectCache; import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException; -import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.maven.MavenCore; /** @@ -50,7 +48,6 @@ public class MavenProjectCache extends AbstractFileToProjectCache { // return artifact.getFile().toPath(); // }), projectResolvedOutput()); - Object classpath = client.classpath(new ClasspathParams(pom.toURI().toString())).get(); ImmutableList classpathEntries = ImmutableList.copyOf(Stream.concat(projectDependencies(project).stream().map(a -> a.getFile().toPath()), projectOutput(project).stream().map(f -> f.toPath())).collect(Collectors.toList())); return classpathEntries; diff --git a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/HtmlJavadocTest.java b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/HtmlJavadocTest.java index ab77e3014..ffcd2e6ba 100644 --- a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/HtmlJavadocTest.java +++ b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/HtmlJavadocTest.java @@ -40,7 +40,7 @@ public class HtmlJavadocTest { JandexClasspath.providerType = JavadocProviderTypes.HTML; testProjectPath = Paths.get(HtmlJavadocTest.class.getResource("/gs-rest-service-cors-boot-1.4.1-with-classpath-file").toURI()); MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute(); - return new MavenJavaProject(null, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); } catch (Exception e) { return null; } diff --git a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java index ba1b1ee25..e556eff8b 100644 --- a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java +++ b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java @@ -47,7 +47,7 @@ public class JavaIndexTest { public MavenJavaProject load(String projectName) throws Exception { Path testProjectPath = Paths.get(DependencyTreeTest.class.getResource("/" + projectName).toURI()); MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute(); - return new MavenJavaProject(null, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); } }); diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/RunnableWithException.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/RunnableWithException.java new file mode 100644 index 000000000..bcbde2918 --- /dev/null +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/RunnableWithException.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2018 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.util; + +@FunctionalInterface +public interface RunnableWithException { + + void run() throws Exception; +} \ No newline at end of file diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java index 47b8fcb2e..374dcb9f5 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java @@ -140,7 +140,7 @@ public class LanguageServerHarness { this.defaultLanguageId = defaultLanguageId; } - public static final Duration HIGHLIGHTS_TIMEOUT = Duration.ofMillis(1_000); //TODO: why does it need to be this long, that's fishy! + public static final Duration HIGHLIGHTS_TIMEOUT = Duration.ofMillis(3_000); public LanguageServerHarness(Callable factory) throws Exception { this(factory, LanguageId.PLAINTEXT); @@ -421,7 +421,7 @@ public class LanguageServerHarness { } public PublishDiagnosticsParams getDiagnostics(TextDocumentInfo doc) throws Exception { - this.getServer().waitForReconcile(); + waitForReconcile(); return diagnostics.get(doc.getUri()); } @@ -468,7 +468,7 @@ public class LanguageServerHarness { TextDocumentPositionParams params = new TextDocumentPositionParams(); params.setPosition(cursor); params.setTextDocument(doc.getId()); - getServer().waitForReconcile(); + waitForReconcile(); Either, CompletionList> completions = getServer().getTextDocumentService().completion(params).get(); if (completions.isLeft()) { List list = completions.getLeft(); @@ -478,6 +478,11 @@ public class LanguageServerHarness { } } + private void waitForReconcile() throws Exception { + getServer().getAsync().waitForAll(); + getServer().waitForReconcile(); + } + public Hover getHover(TextDocumentInfo document, Position cursor) throws Exception { TextDocumentPositionParams params = new TextDocumentPositionParams(); @@ -594,7 +599,7 @@ public class LanguageServerHarness { } public List getDefinitions(TextDocumentPositionParams params) throws Exception { - getServer().waitForReconcile(); //goto definitions relies on reconciler infos! Must wait or race condition breaking tests occasionally. + waitForReconcile(); //goto definitions relies on reconciler infos! Must wait or race condition breaking tests occasionally. return getServer().getTextDocumentService().definition(params).get(); } @@ -661,7 +666,7 @@ public class LanguageServerHarness { } public List getDocumentSymbols(TextDocumentInfo document) throws Exception { - getServer().waitForReconcile(); //TODO: if the server works properly this shouldn't be needed it should do that internally itself somehow. + waitForReconcile(); //TODO: if the server works properly this shouldn't be needed it should do that internally itself somehow. DocumentSymbolParams params = new DocumentSymbolParams(document.getId()); return getServer().getTextDocumentService().documentSymbol(params).get(); } diff --git a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/ConcourseLanguageServer.java b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/ConcourseLanguageServer.java index b4fd05d34..868d05d2a 100644 --- a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/ConcourseLanguageServer.java +++ b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/ConcourseLanguageServer.java @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.concourse; import java.util.List; -import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.CompletionList; import org.eclipse.lsp4j.DiagnosticSeverity; @@ -44,6 +43,8 @@ import org.springframework.ide.vscode.concourse.github.GithubInfoProvider; import com.google.common.collect.ImmutableList; +import reactor.core.publisher.Mono; + public class ConcourseLanguageServer extends SimpleLanguageServer { private final YamlCompletionEngineOptions COMPLETION_OPTIONS; @@ -134,11 +135,11 @@ public class ConcourseLanguageServer extends SimpleLanguageServer { return forTasks.completionEngine.getCompletions(params); } } - return CompletableFuture.completedFuture(new CompletionList(false, ImmutableList.of())); + return Mono.just(new CompletionList(false, ImmutableList.of())); }); documents.onCompletionResolve(item -> { completionResolver.resolveNow(item); - return CompletableFuture.completedFuture(item); + return item; }); documents.onHover(params -> { TextDocument doc = documents.get(params); diff --git a/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveClasspathHandler.java b/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveClasspathHandler.java index 2a75a1251..46b26b81d 100644 --- a/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveClasspathHandler.java +++ b/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveClasspathHandler.java @@ -58,7 +58,7 @@ public class ResolveClasspathHandler implements IDelegateCommandHandler { } } Classpath classpath = new Classpath(cpEntries, javaProject.getOutputLocation().toString()); -// log("classpath=" + classpath); + log("classpath=" + classpath); return classpath; } diff --git a/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveProjectHandler.java b/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveProjectHandler.java index 2ac29dd5c..a7b03400e 100644 --- a/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveProjectHandler.java +++ b/headless-services/org.springframework.tooling.jdt.ls.extension/src/org/springframework/tooling/jdt/ls/extension/ResolveProjectHandler.java @@ -28,7 +28,9 @@ public class ResolveProjectHandler implements IDelegateCommandHandler { log("ResolveProjectHandler=" + commandId); try { URI resourceUri = ResourceUtils.getResourceUri(arguments); - + + log("resourceUri=" + resourceUri); + IJavaProject javaProject = ResourceUtils.getJavaProject(resourceUri); ProjectResponse projectResponse = new ProjectResponse(javaProject.getElementName(), javaProject.getProject().getLocationURI().toString()); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCodeLensEngine.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCodeLensEngine.java index 65fe67df8..59b07e3ea 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCodeLensEngine.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaCodeLensEngine.java @@ -36,14 +36,14 @@ public class BootJavaCodeLensEngine implements CodeLensHandler { } @Override - public CompletableFuture> handle(CodeLensParams params) { + public List handle(CodeLensParams params) { SimpleTextDocumentService documents = server.getTextDocumentService(); String docURI = params.getTextDocument().getUri(); if (documents.get(docURI) != null) { TextDocument doc = documents.get(docURI).copy(); try { - CompletableFuture> codeLensesResult = provideCodeLenses(doc); + List codeLensesResult = provideCodeLenses(doc); if (codeLensesResult != null) { return codeLensesResult; } @@ -55,7 +55,7 @@ public class BootJavaCodeLensEngine implements CodeLensHandler { return SimpleTextDocumentService.NO_CODELENS; } - private CompletableFuture> provideCodeLenses(TextDocument document) { + private List provideCodeLenses(TextDocument document) { return server.getCompilationUnitCache().withCompilationUnit(document, cu -> { if (cu != null) { @@ -65,7 +65,7 @@ public class BootJavaCodeLensEngine implements CodeLensHandler { } if (result.size() > 0) { - return CompletableFuture.completedFuture(result); + return result; } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java index dcd1fef7d..7a57db932 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaHoverProvider.java @@ -64,7 +64,7 @@ public class BootJavaHoverProvider implements HoverHandler { } @Override - public CompletableFuture handle(TextDocumentPositionParams params) { + public Hover handle(TextDocumentPositionParams params) { SimpleTextDocumentService documents = server.getTextDocumentService(); if (documents.get(params) != null) { TextDocument doc = documents.get(params).copy(); @@ -72,7 +72,7 @@ public class BootJavaHoverProvider implements HoverHandler { int offset = doc.toOffset(params.getPosition()); Hover hoverResult = provideHover(doc, offset); if (hoverResult != null) { - return CompletableFuture.completedFuture(hoverResult); + return hoverResult; } } catch (Exception e) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java index b6c81415c..43c6286f4 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaReferencesHandler.java @@ -52,13 +52,13 @@ public class BootJavaReferencesHandler implements ReferencesHandler { } @Override - public CompletableFuture> handle(ReferenceParams params) { + public List handle(ReferenceParams params) { SimpleTextDocumentService documents = server.getTextDocumentService(); TextDocument doc = documents.get(params).copy(); if (doc != null) { try { int offset = doc.toOffset(params.getPosition()); - CompletableFuture> referencesResult = provideReferences(doc, offset); + List referencesResult = provideReferences(doc, offset); if (referencesResult != null) { return referencesResult; } @@ -70,7 +70,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler { return SimpleTextDocumentService.NO_REFERENCES; } - private CompletableFuture> provideReferences(TextDocument document, int offset) throws Exception { + private List provideReferences(TextDocument document, int offset) throws Exception { ASTParser parser = ASTParser.newParser(AST.JLS9); Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); @@ -99,7 +99,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler { return null; } - private CompletableFuture> provideReferencesForAnnotation(ASTNode node, int offset, TextDocument doc) { + private List provideReferencesForAnnotation(ASTNode node, int offset, TextDocument doc) { Annotation annotation = null; while (node != null && !(node instanceof Annotation)) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/ReferenceProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/ReferenceProvider.java index dd0c96f80..c328db993 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/ReferenceProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/ReferenceProvider.java @@ -11,7 +11,6 @@ package org.springframework.ide.vscode.boot.java.handlers; import java.util.List; -import java.util.concurrent.CompletableFuture; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.Annotation; @@ -24,7 +23,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; */ public interface ReferenceProvider { - CompletableFuture> provideReferences(ASTNode node, Annotation annotation, + List provideReferences(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java index 5bc73463d..6011836aa 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java @@ -63,7 +63,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { } @Override - public CompletableFuture> provideReferences(ASTNode node, Annotation annotation, + public List provideReferences(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc) { try { @@ -88,7 +88,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { return null; } - private CompletableFuture> provideReferences(String value, int offset, int nodeStartOffset, TextDocument doc) { + private List provideReferences(String value, int offset, int nodeStartOffset, TextDocument doc) { try { LocalRange range = getPropertyRange(value, offset); @@ -106,7 +106,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { return null; } - public CompletableFuture> findReferencesFromPropertyFiles( + public List findReferencesFromPropertyFiles( Collection workspaceRoots, String propertyKey ) { @@ -121,7 +121,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { .flatMap(Collection::stream) .collect(Collectors.toList()); - return CompletableFuture.completedFuture(locations); + return locations; } } catch (Exception e) { e.printStackTrace(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java index e6aa153d8..e9123555b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java @@ -11,15 +11,12 @@ package org.springframework.ide.vscode.boot.jdt.ls; import java.io.File; -import java.net.URI; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.slf4j.Logger; @@ -29,9 +26,9 @@ import org.springframework.ide.vscode.commons.java.ClasspathData; import org.springframework.ide.vscode.commons.java.IClasspath; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.IJavadocProvider; +import org.springframework.ide.vscode.commons.languageserver.ClasspathParams; import org.springframework.ide.vscode.commons.languageserver.ClasspathResponse; import org.springframework.ide.vscode.commons.languageserver.ProjectResponse; -import org.springframework.ide.vscode.commons.languageserver.ClasspathParams; import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java index d29075562..fa726e683 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java @@ -38,10 +38,9 @@ public class PropertyReferenceFinderTest { ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI()); - CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); + List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); - assertNotNull(resultFuture); - List locations = resultFuture.get(); + assertNotNull(locations); assertEquals(1, locations.size()); Location location = locations.get(0); @@ -68,10 +67,9 @@ public class PropertyReferenceFinderTest { ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-yml/").toURI()); - CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); + List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); - assertNotNull(resultFuture); - List locations = resultFuture.get(); + assertNotNull(locations); assertEquals(1, locations.size()); Location location = locations.get(0); @@ -88,10 +86,9 @@ public class PropertyReferenceFinderTest { ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI()); - CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(wsFolder(root), "server.port"); + List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "server.port"); - assertNotNull(resultFuture); - List locations = resultFuture.get(); + assertNotNull(locations); assertEquals(1, locations.size()); Location location = locations.get(0); @@ -108,10 +105,9 @@ public class PropertyReferenceFinderTest { ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/multiple-files/").toURI()); - CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); + List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); - assertNotNull(resultFuture); - List locations = resultFuture.get(); + assertNotNull(locations); assertEquals(3, locations.size()); Location location = getLocation(locations, Paths.get(root.toString(), "application-dev.properties").toUri()); @@ -151,10 +147,9 @@ public class PropertyReferenceFinderTest { ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/mixed-multiple-files/").toURI()); - CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); + List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); - assertNotNull(resultFuture); - List locations = resultFuture.get(); + assertNotNull(locations); assertEquals(2, locations.size()); Location location = getLocation(locations, Paths.get(root.toString(), "application-dev.properties").toUri()); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java index 3e446d78e..786c75a65 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java @@ -86,6 +86,7 @@ public class CompilationUnitCacheTest { } private CompilationUnit getCompilationUnit(TextDocument doc) { + harness.getServerWrapper().getServer().getAsync().waitForAll(); return harness.getServerWrapper().getComponents().getCompilationUnitCache().withCompilationUnit(doc, cu -> cu); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java index 181555c8c..455ca32aa 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java @@ -43,7 +43,7 @@ public class VSCodeSourceLinksTest { public MavenJavaProject load(String projectName) throws Exception { Path testProjectPath = Paths.get(VSCodeSourceLinksTest.class.getResource("/test-projects/" + projectName).toURI()); MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute(); - return new MavenJavaProject(null, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); } }); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java index 8070add5c..3aebfd170 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java @@ -101,7 +101,7 @@ public class ProjectsHarness { switch (type) { case MAVEN: MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute(); - return new MavenJavaProject(null, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); case CLASSPATH_TXT: MavenBuilder.newBuilder(testProjectPath).clean().pack().skipTests().execute(); return new JavaProjectWithClasspathFile(testProjectPath.resolve(MavenCore.CLASSPATH_TXT).toFile()); diff --git a/vscode-extensions/commons-vscode/src/classpath-service.ts b/vscode-extensions/commons-vscode/src/classpath.ts similarity index 100% rename from vscode-extensions/commons-vscode/src/classpath-service.ts rename to vscode-extensions/commons-vscode/src/classpath.ts diff --git a/vscode-extensions/commons-vscode/src/launch-util.ts b/vscode-extensions/commons-vscode/src/launch-util.ts index eac880d14..eef9b0374 100644 --- a/vscode-extensions/commons-vscode/src/launch-util.ts +++ b/vscode-extensions/commons-vscode/src/launch-util.ts @@ -15,8 +15,8 @@ import {HighlightService, HighlightParams} from './highlight-service'; import { log } from 'util'; import { tmpdir } from 'os'; import { JVM, findJvm, findJdk } from '@pivotal-tools/jvm-launch-utils'; -import { registerClasspathService } from './classpath-service'; -import { registerProjectService } from './project-service'; +import { registerClasspathService } from './classpath'; +import { registerProjectService } from './project'; let p2c = P2C.createConverter(); @@ -48,11 +48,12 @@ function getUserDefinedJvmHeap(wsOpts : VSCode.WorkspaceConfiguration, dflt : s return javaOptions.heap || dflt; } -export function activate(options: ActivatorOptions, context: VSCode.ExtensionContext): Promise { +export function activate(options: ActivatorOptions, context: VSCode.ExtensionContext): Thenable { let DEBUG = options.DEBUG; let jvmHeap = getUserDefinedJvmHeap(options.workspaceOptions, options.jvmHeap); if (options.CONNECT_TO_LS) { - return connectToLS(context, options); + return VSCode.window.showInformationMessage("Start language server") + .then((x) => connectToLS(context, options)); } else { let clientOptions = options.clientOptions; diff --git a/vscode-extensions/commons-vscode/src/project-service.ts b/vscode-extensions/commons-vscode/src/project.ts similarity index 84% rename from vscode-extensions/commons-vscode/src/project-service.ts rename to vscode-extensions/commons-vscode/src/project.ts index 63614a0f8..1291fc79f 100644 --- a/vscode-extensions/commons-vscode/src/project-service.ts +++ b/vscode-extensions/commons-vscode/src/project.ts @@ -7,8 +7,8 @@ import { LanguageClient, RequestType } from 'vscode-languageclient'; export function registerProjectService(client : LanguageClient) : void { let projectRequest = new RequestType("sts/project"); - client.onRequest(projectRequest, async (uri: string) => { - return await executeProjectCommand(uri); + client.onRequest(projectRequest, (uri: string) => { + return executeProjectCommand(uri); }); }