Attempt to implement some classpath callback cleanups
This commit is contained in:
@@ -17,7 +17,6 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
|
||||
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
|
||||
import org.eclipse.lsp4j.services.LanguageClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerResponse;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit.CursorMovement;
|
||||
|
||||
/**
|
||||
@@ -43,5 +42,8 @@ public interface STS4LanguageClient extends LanguageClient {
|
||||
CompletableFuture<ProjectResponse> project(String uri);
|
||||
|
||||
@JsonRequest("sts/addClasspathListener")
|
||||
CompletableFuture<ClasspathListenerResponse> addClasspathListener(ClasspathListenerParams params);
|
||||
CompletableFuture<Object> addClasspathListener(ClasspathListenerParams params);
|
||||
|
||||
@JsonRequest("sts/removeClasspathListener")
|
||||
CompletableFuture<Object> removeClasspathListener(ClasspathListenerParams classpathListenerParams);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,14 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.Registration;
|
||||
import org.eclipse.lsp4j.RegistrationParams;
|
||||
import org.eclipse.lsp4j.Unregistration;
|
||||
import org.eclipse.lsp4j.UnregistrationParams;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.AsyncRunner;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
@@ -28,10 +31,13 @@ import com.google.gson.JsonElement;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.util.AsyncRunner.*;
|
||||
|
||||
public class ClasspathListenerManager {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(ClasspathListenerManager.class);
|
||||
|
||||
private static final String WORKSPACE_EXECUTE_COMMAND = "workspace/executeCommand";
|
||||
private int commandIdCounter = 0;
|
||||
private SimpleLanguageServer server;
|
||||
private AsyncRunner async;
|
||||
|
||||
@@ -41,7 +47,8 @@ public class ClasspathListenerManager {
|
||||
}
|
||||
|
||||
public Disposable addClasspathListener(ClasspathListener classpathListener) {
|
||||
String callbackCommandId = "sts4.classpath." + (commandIdCounter++);
|
||||
String callbackCommandId = "sts4.classpath." + RandomStringUtils.randomAlphabetic(8);
|
||||
|
||||
// 1. register callback command handler in SimpleLanguageServer
|
||||
Disposable unregisterCommand = server.onCommand(callbackCommandId, (ExecuteCommandParams callbackParams) -> async.invoke(() -> {
|
||||
List<Object> args = callbackParams.getArguments();
|
||||
@@ -54,7 +61,9 @@ public class ClasspathListenerManager {
|
||||
}));
|
||||
|
||||
// 2. call the client to ask it to call that callback
|
||||
CompletableFuture<ClasspathListenerResponse> future1 = server.getClient().addClasspathListener(new ClasspathListenerParams(callbackCommandId));
|
||||
CompletableFuture<Object> future1 = server.getClient().addClasspathListener(
|
||||
new ClasspathListenerParams(callbackCommandId)
|
||||
);
|
||||
|
||||
// 2. register the callback command with the client
|
||||
String registrationId = UUID.randomUUID().toString();
|
||||
@@ -73,6 +82,7 @@ public class ClasspathListenerManager {
|
||||
// Cleanups:
|
||||
return () -> {
|
||||
unregisterCommand.dispose();
|
||||
thenLog(log, this.server.getClient().removeClasspathListener(new ClasspathListenerParams(callbackCommandId)));
|
||||
this.server.getClient().unregisterCapability(new UnregistrationParams(ImmutableList.of(
|
||||
new Unregistration(registrationId, WORKSPACE_EXECUTE_COMMAND)
|
||||
)));
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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.jdt.ls;
|
||||
|
||||
public class ClasspathListenerResponse {
|
||||
|
||||
}
|
||||
@@ -37,15 +37,19 @@ public class AsyncRunner {
|
||||
return x;
|
||||
}
|
||||
|
||||
public synchronized void withLog(Logger logger, RunnableWithException runnable) {
|
||||
execute(runnable).handle((v, e) -> {
|
||||
public static void thenLog(Logger log, CompletableFuture<?> work) {
|
||||
work.handle((v, e) -> {
|
||||
if (e!=null) {
|
||||
logger.error("", e);
|
||||
log.error("", e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void withLog(Logger logger, RunnableWithException runnable) {
|
||||
thenLog(logger, execute(runnable));
|
||||
}
|
||||
|
||||
public synchronized CompletableFuture<Void> execute(RunnableWithException runnable) {
|
||||
CompletableFuture<Void> x = Mono.fromCallable(() -> {
|
||||
runnable.run();
|
||||
|
||||
@@ -98,7 +98,6 @@ import org.springframework.ide.vscode.commons.languageserver.ProjectResponse;
|
||||
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerResponse;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit.CursorMovement;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.LanguageServerTestListener;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
|
||||
@@ -308,9 +307,15 @@ public class LanguageServerHarness<S extends SimpleLanguageServerWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ClasspathListenerResponse> addClasspathListener(
|
||||
public CompletableFuture<Object> addClasspathListener(
|
||||
ClasspathListenerParams params) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
return CompletableFuture.completedFuture("ok");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Object> removeClasspathListener(
|
||||
ClasspathListenerParams classpathListenerParams) {
|
||||
return CompletableFuture.completedFuture("ok");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -21,10 +21,12 @@ public class ClasspathListenerHandler implements IDelegateCommandHandler {
|
||||
private List<String> subscribers = new ArrayList<>(1);
|
||||
|
||||
public synchronized void subscribe(String callbackCommandId) {
|
||||
Logger.log("subscribing to classpath changes: "+callbackCommandId);
|
||||
if (manager==null) {
|
||||
this.manager = new ClasspathListenerManager(this);
|
||||
}
|
||||
subscribers.add(callbackCommandId);
|
||||
Logger.log("subsribers = "+subscribers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,6 +39,21 @@ public class ClasspathListenerHandler implements IDelegateCommandHandler {
|
||||
conn.executeCommand(callbackCommandId, project, deleted);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void unsubscribe(String callbackCommandId) {
|
||||
Logger.log("unsubscribing from classpath changes: "+callbackCommandId);
|
||||
if (subscribers!=null) {
|
||||
subscribers.remove(callbackCommandId);
|
||||
if (subscribers.isEmpty()) {
|
||||
subscribers = null;
|
||||
if (manager!=null) {
|
||||
manager.dispose();
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger.log("subsribers = "+subscribers);
|
||||
}
|
||||
}
|
||||
|
||||
private static MyClasspathListener classpathListener = new MyClasspathListener();
|
||||
@@ -44,10 +61,21 @@ public class ClasspathListenerHandler implements IDelegateCommandHandler {
|
||||
@Override
|
||||
public Object executeCommand(String commandId, List<Object> arguments, IProgressMonitor monitor) throws Exception {
|
||||
log("ClasspathListenerHandler executeCommand "+commandId+ ", "+arguments);
|
||||
if (commandId.equals("sts.java.addClasspathListener")) {
|
||||
switch (commandId) {
|
||||
case "sts.java.addClasspathListener":
|
||||
return addClasspathListener((String)arguments.get(0));
|
||||
case "sts.java.removeClasspathListener":
|
||||
return removeClasspathListener((String)arguments.get(0));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown command id: "+commandId);
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown command id: "+commandId);
|
||||
}
|
||||
|
||||
private Object removeClasspathListener(String callbackCommandId) {
|
||||
log("ClasspathListenerHandler addClasspathListener "+callbackCommandId);
|
||||
classpathListener.unsubscribe(callbackCommandId);
|
||||
log("ClasspathListenerHandler addClasspathListener "+callbackCommandId+ " => OK");
|
||||
return "ok";
|
||||
}
|
||||
|
||||
private Object addClasspathListener(String callbackCommandId) {
|
||||
|
||||
@@ -60,7 +60,9 @@ public class JdtLsProjectCache implements JavaProjectFinder, ProjectObserver {
|
||||
}
|
||||
}))
|
||||
);
|
||||
this.server.onShutdown(() -> disposable.thenAccept(Disposable::dispose));
|
||||
this.server.onShutdown(() ->
|
||||
disposable.thenAccept(Disposable::dispose)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user