Use LSP progress instead of our own LSP extension

This commit is contained in:
BoykoAlex
2022-01-14 19:23:38 -05:00
parent 231755d8eb
commit f36671814c
11 changed files with 86 additions and 114 deletions

View File

@@ -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) {

View File

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

View File

@@ -32,7 +32,7 @@ public class ProgressTask {
}
public void progressDone() {
this.service.progressDone(taskId);
this.service.progressEvent(taskId, null);
}
}

View File

@@ -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<TextEdit> 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 {

View File

@@ -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<String, Boolean> 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);
}
}
};

View File

@@ -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<Object> moveCursor(CursorMovement cursorMovement);

View File

@@ -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();

View File

@@ -326,10 +326,12 @@ public class LanguageServerHarness {
public CompletableFuture<Void> 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

View File

@@ -99,7 +99,7 @@
<mockito-version>1.10.19</mockito-version>
<jackson-2-version>2.5.0</jackson-2-version>
<jersey-2-version>2.10</jersey-2-version>
<lsp4j-version>0.9.0</lsp4j-version>
<lsp4j-version>0.12.0</lsp4j-version>
<!-- NOTE: Reactor version must match version used by the CF client -->
<cloudfoundry-client-version>3.8.0.RELEASE</cloudfoundry-client-version>
<reactor-version>3.1.5.RELEASE</reactor-version>

View File

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

View File

@@ -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<LanguageClient> {
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<ProgressParams>("sts/progress");
let highlightNotification = new NotificationType<HighlightParams>("sts/highlight");
let moveCursorRequest = new RequestType<MoveCursorParams,MoveCursorResponse,void>("sts/moveCursor");
@@ -333,7 +328,6 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser
const codeLensListanableSetting = options.highlightCodeLensSettingKey ? new ListenablePreferenceSetting<boolean>(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<String, ProgressHandle>();
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<T> {
value: T;
onDidChangeValue: VSCode.Event<void>