~damien/jedit-lsp

83b9ba84cf54751d582d0a53a80aae4ef890c84c — Damien Radtke 3 months ago c132703
Handle unknown notifications and requests
2 files changed, 71 insertions(+), 1 deletions(-)

A lsp/MessageWrapper.java
M lsp/Server.java
A lsp/MessageWrapper.java => lsp/MessageWrapper.java +60 -0
@@ 0,0 1,60 @@
package lsp;

import java.util.function.Function;

import com.google.gson.JsonObject;

import org.eclipse.lsp4j.jsonrpc.JsonRpcException;
import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.RequestMessage;
import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage;

import org.gjt.sp.util.Log;
import org.gjt.sp.util.ThreadUtilities;

public class MessageWrapper implements Function<MessageConsumer, MessageConsumer> {
	@Override
	public MessageConsumer apply(MessageConsumer consumer) {
		return new Consumer(consumer);
	}

	class Consumer implements MessageConsumer {
		private MessageConsumer original;

		Consumer(MessageConsumer original) {
			this.original = original;
		}

		@Override
		public void consume(Message message) throws MessageIssueException, JsonRpcException {
			try {
				if (message instanceof NotificationMessage) {
					NotificationMessage notification = (NotificationMessage) message;
					switch (notification.getMethod()) {
						case "language/status":
							ThreadUtilities.runInDispatchThread(() -> {
								JsonObject params = (JsonObject) notification.getParams();
								String statusType = params.get("type").getAsString();
								String statusMessage = params.get("message").getAsString();
								Utils.showTemporaryMessage(statusMessage);
							});
							return;
					}
				} else if (message instanceof RequestMessage) {
					RequestMessage request = (RequestMessage) message;
					switch (request.getMethod()) {
						case "workspace/executeClientCommand":
							Log.log(Log.WARNING, this, "Unimplemented client command: " + message.toString());
							return;
					}
				}
				this.original.consume(message);
			} catch (Exception e) {
				Log.log(Log.ERROR, this, "Exception while consuming message: " + message.toString(), e);
				this.original.consume(message);
			}
		}
	}
}

M lsp/Server.java => lsp/Server.java +11 -1
@@ 22,6 22,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;



@@ 165,7 166,16 @@ public class Server {
			try {
				synchronized(this) {
					this.process.start();
					this.handle = LSPLauncher.createClientLauncher(this.client, process.getOutput(), process.getInput());
					// ???: Use the variant that lets us define a wrapper for each message?
					// Alternatively, it looks like this.client could _potentially_ be translated
					// into an Endpoint implementation
					this.handle = LSPLauncher.createClientLauncher(
						this.client,
						process.getOutput(),
						process.getInput(),
						Executors.newCachedThreadPool(),
						new MessageWrapper()
					);
					Future<Void> serverDone = this.handle.startListening(); // ???: wait on the returned future?
					ThreadUtilities.runInBackground(new Task("Running language server: " + process.getName(), () -> wait(serverDone, process.getLog())));
					log(Log.NOTICE, "Started server: " + process.getName() + " for " + buffer.getPath());