Use LSP progress instead of our own LSP extension
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ProgressTask {
|
||||
}
|
||||
|
||||
public void progressDone() {
|
||||
this.service.progressDone(taskId);
|
||||
this.service.progressEvent(taskId, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user