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); }); }