Attempt to implement some classpath callback cleanups

This commit is contained in:
Kris De Volder
2018-03-15 17:43:17 -07:00
parent 64a45984ce
commit 39ffe531e6
7 changed files with 65 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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