Fix for long hang on reconcile

This commit is contained in:
nsingh
2017-02-01 16:00:51 -08:00
parent c9178f8b55
commit c1bc20029a
3 changed files with 37 additions and 8 deletions

View File

@@ -40,6 +40,10 @@ import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Futures;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
/**
* Abstract base class to implement LanguageServer. Bits and pieces copied from
* the 'JavaLanguageServer' example which seem generally useful / reusable end up in
@@ -50,6 +54,8 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
private static final Logger LOG = Logger.getLogger(SimpleLanguageServer.class.getName());
private static final Scheduler RECONCILER_SCHEDULER = Schedulers.newSingle("Reconciler");
private Path workspaceRoot;
private SimpleTextDocumentService tds;
@@ -65,6 +71,8 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
}
};
private CompletableFuture<Void> busyReconcile = CompletableFuture.completedFuture(null);
@Override
public void connect(LanguageClient _client) {
this.client = (STS4LanguageClient) _client;
@@ -150,7 +158,10 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
* Convenience method. Subclasses can call this to use a {@link IReconcileEngine} ported
* from old STS codebase to validate a given {@link TextDocument} and publish Diagnostics.
*/
protected void validateWith(TextDocument doc, IReconcileEngine engine) {
protected void validateWith(TextDocument _doc, IReconcileEngine engine) {
TextDocument doc = _doc.copy();
this.busyReconcile = new CompletableFuture<Void>();
SimpleTextDocumentService documents = getTextDocumentService();
IProblemCollector problems = new IProblemCollector() {
@@ -198,7 +209,23 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
}
}
};
engine.reconcile(doc, problems);
// Avoid running in the same thread as lsp4j as it can result
// in long "hangs" for slow reconcile providers
Mono.fromRunnable(() -> {
engine.reconcile(doc, problems);
})
.doOnTerminate((ignore1, ignore2) -> {
busyReconcile.complete(null);
})
.subscribeOn(RECONCILER_SCHEDULER)
.subscribe();
}
public void waitForReconcile() throws Exception {
while (!this.busyReconcile.isDone()) {
this.busyReconcile.get();
}
}
public LanguageClient getClient() {

View File

@@ -221,7 +221,7 @@ public class Editor {
: "";
}
private List<Diagnostic> reconcile() {
private List<Diagnostic> reconcile() throws Exception {
// We assume the language server works synchronously for now and it does an immediate reconcile
// when the document changes. In the future this is probably not going to be the case though and then this
// method will need to somehow ensure the linter is done working before retrieving the problems from the

View File

@@ -54,6 +54,7 @@ import org.eclipse.lsp4j.services.LanguageServer;
import org.springframework.ide.vscode.commons.languageserver.LanguageIds;
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
public class LanguageServerHarness {
@@ -61,10 +62,10 @@ public class LanguageServerHarness {
private Random random = new Random();
private Callable<? extends LanguageServer> factory;
private Callable<? extends SimpleLanguageServer> factory;
private String defaultLanguageId;
private LanguageServer server;
private SimpleLanguageServer server;
private InitializeResult initResult;
@@ -72,12 +73,12 @@ public class LanguageServerHarness {
private Map<String, PublishDiagnosticsParams> diagnostics = new HashMap<>();
public LanguageServerHarness(Callable<? extends LanguageServer> factory, String defaultLanguageId) {
public LanguageServerHarness(Callable<? extends SimpleLanguageServer> factory, String defaultLanguageId) {
this.factory = factory;
this.defaultLanguageId = defaultLanguageId;
}
public LanguageServerHarness(Callable<? extends LanguageServer> factory) throws Exception {
public LanguageServerHarness(Callable<? extends SimpleLanguageServer> factory) throws Exception {
this(factory, LanguageIds.PLAINTEXT);
}
@@ -263,7 +264,8 @@ public class LanguageServerHarness {
return TextDocumentSyncKind.None;
}
public PublishDiagnosticsParams getDiagnostics(TextDocumentInfo doc) {
public PublishDiagnosticsParams getDiagnostics(TextDocumentInfo doc) throws Exception {
this.server.waitForReconcile();
return diagnostics.get(doc.getUri());
}