From f36671814cfc103302458219d2fb528a455eef37 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Fri, 14 Jan 2022 19:23:38 -0500 Subject: [PATCH] Use LSP progress instead of our own LSP extension --- .../commons/STS4LanguageClientImpl.java | 27 +++++- .../languageserver/ProgressService.java | 8 +- .../commons/languageserver/ProgressTask.java | 2 +- .../VscodeCompletionEngineAdapter.java | 3 +- .../util/SimpleLanguageServer.java | 51 +++++++++-- .../commons/protocol/STS4LanguageClient.java | 3 - .../languageserver/testharness/Editor.java | 2 +- .../testharness/LanguageServerHarness.java | 6 +- headless-services/commons/pom.xml | 2 +- .../test/ApplicationPropertiesEditorTest.java | 6 +- .../commons-vscode/src/launch-util.ts | 90 +------------------ 11 files changed, 86 insertions(+), 114 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java index f1a6d06df..53c98541d 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java @@ -55,6 +55,9 @@ import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.MarkupContent; import org.eclipse.lsp4j.MarkupKind; import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.WorkDoneProgressBegin; +import org.eclipse.lsp4j.WorkDoneProgressNotification; +import org.eclipse.lsp4j.WorkDoneProgressReport; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; @@ -356,10 +359,28 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La } } + + @Override - public void progress(ProgressParams progressEvent) { - String status = progressEvent.getStatusMsg() != null ? progressEvent.getStatusMsg() : ""; - showStatusMessage(status); + public void notifyProgress(org.eclipse.lsp4j.ProgressParams params) { + if (params.getValue().isLeft()) { + WorkDoneProgressNotification progressNotification = params.getValue().getLeft(); + switch (progressNotification.getKind()) { + case begin: + WorkDoneProgressBegin begin = (WorkDoneProgressBegin) progressNotification; + showStatusMessage(begin.getMessage()); + break; + case report: + WorkDoneProgressReport report = (WorkDoneProgressReport) progressNotification; + showStatusMessage(report.getMessage()); + break; + case end: + showStatusMessage(""); + break; + default: + break; + } + } } private void showStatusMessage(final String status) { diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java index 87cad508f..32812628f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java @@ -20,10 +20,6 @@ public interface ProgressService { } - @Override - public void progressDone(String taskId) { - - } }; /** @@ -43,9 +39,7 @@ public interface ProgressService { * @param statusMsg */ void progressEvent(String taskId, String statusMsg); - - void progressDone(String taskId); - + default ProgressTask createProgressTask(String taskId) { return new ProgressTask(taskId, this); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressTask.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressTask.java index f4a45e4a4..f6176bdd1 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressTask.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressTask.java @@ -32,7 +32,7 @@ public class ProgressTask { } public void progressDone() { - this.service.progressDone(taskId); + this.service.progressEvent(taskId, null); } } 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 9dbb0eef5..a43add9b0 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 @@ -30,6 +30,7 @@ import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.TextDocumentPositionParams; import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.jsonrpc.CancelChecker; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits.TextReplace; @@ -254,7 +255,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { AtomicBoolean usedSnippets = new AtomicBoolean(); Optional mainEdit = adaptEdits(doc, completion.getTextEdit(), usedSnippets); if (mainEdit.isPresent()) { - item.setTextEdit(mainEdit.get()); + item.setTextEdit(Either.forLeft(mainEdit.get())); if (server.hasCompletionSnippetSupport()) { item.setInsertTextFormat(usedSnippets.get() ? InsertTextFormat.Snippet : InsertTextFormat.PlainText); } else { 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 341cef071..9583f72b5 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 @@ -26,6 +26,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -42,6 +43,7 @@ import org.eclipse.lsp4j.InitializeParams; import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; +import org.eclipse.lsp4j.ProgressParams; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.Registration; import org.eclipse.lsp4j.RegistrationParams; @@ -49,9 +51,14 @@ import org.eclipse.lsp4j.ServerCapabilities; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.eclipse.lsp4j.TextDocumentSyncKind; import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; +import org.eclipse.lsp4j.WorkDoneProgressBegin; +import org.eclipse.lsp4j.WorkDoneProgressCreateParams; +import org.eclipse.lsp4j.WorkDoneProgressEnd; +import org.eclipse.lsp4j.WorkDoneProgressReport; import org.eclipse.lsp4j.WorkspaceFolder; import org.eclipse.lsp4j.WorkspaceFoldersOptions; import org.eclipse.lsp4j.WorkspaceServerCapabilities; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.LanguageClientAware; import org.slf4j.Logger; @@ -76,7 +83,6 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.Diagnosti import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine; import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem; -import org.springframework.ide.vscode.commons.protocol.ProgressParams; import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient; import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.AsyncRunner; @@ -121,18 +127,51 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC private final LanguageServerProperties props; private ProgressService progressService = new ProgressService() { - + + private ConcurrentHashMap activeTaskIDs = new ConcurrentHashMap<>(); + @Override public void progressEvent(String taskId, String statusMsg) { STS4LanguageClient client = SimpleLanguageServer.this.client; if (client!=null) { - client.progress(new ProgressParams(taskId, statusMsg)); + if (statusMsg == null) { + progressDone(taskId); + return; + } + boolean isNew = activeTaskIDs.put(taskId, true) == null; + if (isNew) { + // New taskId, new progress + WorkDoneProgressCreateParams params = new WorkDoneProgressCreateParams(); + params.setToken(taskId); + SimpleLanguageServer.this.client.createProgress(params).thenAccept((p) -> { + ProgressParams progressParams = new ProgressParams(); + progressParams.setToken(taskId); + WorkDoneProgressBegin report = new WorkDoneProgressBegin(); + report.setCancellable(false); + progressParams.setValue(Either.forLeft(report)); + report.setMessage(statusMsg); + SimpleLanguageServer.this.client.notifyProgress(progressParams); + }); + } else { + // Already exists + ProgressParams progressParams = new ProgressParams(); + progressParams.setToken(taskId); + WorkDoneProgressReport report = new WorkDoneProgressReport(); + progressParams.setValue(Either.forLeft(report)); + report.setMessage(statusMsg); + SimpleLanguageServer.this.client.notifyProgress(progressParams); + } } } - @Override - public void progressDone(String taskId) { - progressEvent(taskId, null); + private void progressDone(String taskId) { + if (activeTaskIDs.remove(taskId)) { + ProgressParams progressParams = new ProgressParams(); + progressParams.setToken(taskId); + WorkDoneProgressEnd report = new WorkDoneProgressEnd(); + progressParams.setValue(Either.forLeft(report)); + SimpleLanguageServer.this.client.notifyProgress(progressParams); + } } }; diff --git a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/STS4LanguageClient.java b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/STS4LanguageClient.java index a874195ff..360774aa8 100644 --- a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/STS4LanguageClient.java +++ b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/STS4LanguageClient.java @@ -39,9 +39,6 @@ public interface STS4LanguageClient extends LanguageClient { @JsonNotification("sts/highlight") void highlight(HighlightParams highlights); - @JsonNotification("sts/progress") - void progress(ProgressParams progressEvent); - @JsonRequest("sts/moveCursor") CompletableFuture moveCursor(CursorMovement cursorMovement); diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java index 6137080bc..60366f1c0 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java @@ -451,7 +451,7 @@ public class Editor { public void apply(CompletionItem completion) throws Exception { completion = harness.resolveCompletionItem(completion); - TextEdit edit = completion.getTextEdit(); + TextEdit edit = completion.getTextEdit().getLeft(); String docText = doc.getText(); if (edit!=null) { String replaceWith = edit.getNewText(); 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 0dbf23ff5..5d0d475b7 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 @@ -326,10 +326,12 @@ public class LanguageServerHarness { public CompletableFuture registerCapability(RegistrationParams params) { return CompletableFuture.completedFuture(null); } + + @Override - public void progress(ProgressParams progressEvent) { - // TODO Auto-generated method stub + public void notifyProgress(org.eclipse.lsp4j.ProgressParams params) { + // nothing } @Override diff --git a/headless-services/commons/pom.xml b/headless-services/commons/pom.xml index cb0f5c28e..52c2fbf26 100644 --- a/headless-services/commons/pom.xml +++ b/headless-services/commons/pom.xml @@ -99,7 +99,7 @@ 1.10.19 2.5.0 2.10 - 0.9.0 + 0.12.0 3.8.0.RELEASE 3.1.5.RELEASE diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java index 1acb28396..35d4b42c7 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java @@ -184,7 +184,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "long.foobar.more" ); for (CompletionItem c : completions) { - TextEdit edit = c.getTextEdit(); + TextEdit edit = c.getTextEdit().getLeft(); assertEquals("bar", editor.getText(edit.getRange())); } @@ -202,7 +202,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "very.long.foofoo.more" ); for (CompletionItem c : completions) { - TextEdit edit = c.getTextEdit(); + TextEdit edit = c.getTextEdit().getLeft(); assertEquals("vr", editor.getText(edit.getRange())); } @@ -230,7 +230,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "long.foofoo.more" ); for (CompletionItem c : completions) { - TextEdit edit = c.getTextEdit(); + TextEdit edit = c.getTextEdit().getLeft(); assertEquals("", editor.getText(edit.getRange())); } diff --git a/vscode-extensions/commons-vscode/src/launch-util.ts b/vscode-extensions/commons-vscode/src/launch-util.ts index 9d7763092..f834699d6 100644 --- a/vscode-extensions/commons-vscode/src/launch-util.ts +++ b/vscode-extensions/commons-vscode/src/launch-util.ts @@ -5,17 +5,13 @@ import * as Path from 'path'; import * as FS from 'fs'; import PortFinder = require('portfinder'); import * as Net from 'net'; -import * as ChildProcess from 'child_process'; import * as CommonsCommands from './commands'; import { RequestType, LanguageClientOptions, Position } from 'vscode-languageclient'; import {LanguageClient, StreamInfo, ServerOptions, ExecutableOptions, Executable} from 'vscode-languageclient/node'; import { Disposable, - window, Event, - EventEmitter, - ProgressLocation, - Progress, + EventEmitter } from 'vscode'; import { Trace, NotificationType } from 'vscode-jsonrpc'; import * as P2C from 'vscode-languageclient/lib/common/protocolConverter'; @@ -115,7 +111,7 @@ function getJdtUserDefinedJavaHome(log: VSCode.OutputChannel): string { export function activate(options: ActivatorOptions, context: VSCode.ExtensionContext): Thenable { if (options.CONNECT_TO_LS) { return VSCode.window.showInformationMessage("Start language server") - .then((x) => connectToLS(context, options)); + .then((_) => connectToLS(context, options)); } else { const clientOptions = options.clientOptions; @@ -178,7 +174,7 @@ function createServerOptions(options: ActivatorOptions, context: VSCode.Extensio function createServerOptionsForPortComm(options: ActivatorOptions, context: VSCode.ExtensionContext, jvm: JVM): ServerOptions { return () => - new Promise((resolve, reject) => { + new Promise((resolve) => { PortFinder.getPort((err, port) => { Net.createServer(socket => { options.clientOptions.outputChannel.appendLine('Child process connected on port ' + port); @@ -325,7 +321,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser client.trace = Trace.Verbose; } - let progressNotification = new NotificationType("sts/progress"); let highlightNotification = new NotificationType("sts/highlight"); let moveCursorRequest = new RequestType("sts/moveCursor"); @@ -333,7 +328,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser const codeLensListanableSetting = options.highlightCodeLensSettingKey ? new ListenablePreferenceSetting(options.highlightCodeLensSettingKey) : undefined; - let progressService = new ProgressService(); let highlightService = new HighlightService(); const codelensService = new HighlightCodeLensProvider(); let codeLensProviderSubscription: Disposable; @@ -341,7 +335,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser CommonsCommands.registerCommands(context); context.subscriptions.push(disposable); - context.subscriptions.push(progressService); context.subscriptions.push(highlightService); function toggleHighlightCodeLens() { @@ -364,9 +357,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser } return client.onReady().then(() => { - client.onNotification(progressNotification, (params: ProgressParams) => { - progressService.handle(params); - }); client.onNotification(highlightNotification, (params: HighlightParams) => { highlightService.handle(params); if (codeLensListanableSetting && codeLensListanableSetting.value) { @@ -374,8 +364,7 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser } }); client.onRequest(moveCursorRequest, (params: MoveCursorParams) => { - let editors = VSCode.window.visibleTextEditors; - for (let editor of editors) { + for (let editor of VSCode.window.visibleTextEditors) { if (editor.document.uri.toString() == params.uri) { let cursor = p2c.asPosition(params.position); let selection : VSCode.Selection = new VSCode.Selection(cursor, cursor); @@ -390,13 +379,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser }); } -function correctBinname(binname: string) { - if (process.platform === 'win32') - return binname + '.exe'; - else - return binname; -} - interface MoveCursorParams { uri: string position: Position @@ -406,70 +388,6 @@ interface MoveCursorResponse { applied: boolean } -interface ProgressParams { - id: string - title: string - statusMsg?: string -} - -class ProgressHandle { - constructor( - private progress: Progress<{ message?: string; increment?: number }>, - private finish: () => void - ) {} - - updateStatus(message: string, increment: number) { - this.progress.report({ - message, - increment - }); - } - - complete() { - this.finish(); - } -} - -class ProgressService { - - private status = new Map(); - - handle(params: ProgressParams) { - const progressHandler = this.status.get(params.id); - if (progressHandler) { - if(params.statusMsg) { - progressHandler.updateStatus(params.statusMsg, -1); - } else { - progressHandler.complete(); - } - } else { - if (params.statusMsg) { - window.withProgress({ - location: ProgressLocation.Notification, - title: "", - cancellable: false - }, progress => new Promise(resolve => { - this.status.set(params.id, new ProgressHandle(progress, <() => void>resolve)); - progress.report({ - message: params.statusMsg, - increment: -1 - }) - })); - } - } - - } - - dispose() { - if (this.status) { - for (let handler of this.status.values()) { - handler.complete(); - } - } - this.status = null; - } -} - export interface ListenableSetting { value: T; onDidChangeValue: VSCode.Event