added cancel handling to hover requests

This commit is contained in:
Martin Lippert
2021-02-26 12:03:48 +01:00
parent 7864692cb0
commit 4a3650c0b1
7 changed files with 59 additions and 30 deletions

View File

@@ -17,6 +17,7 @@ import java.util.Set;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
@@ -81,14 +82,14 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
//Create composite hover handler
this.hoverHandler = new HoverHandler() {
@Override
public Hover handle(HoverParams params) {
public Hover handle(CancelChecker cancelToken, HoverParams params) {
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri());
LanguageId language = doc.getLanguageId();
LanguageServerComponents subComponents = componentsByLanguageId.get(language);
if (subComponents!=null) {
if (subComponents != null) {
HoverHandler subEngine = subComponents.getHoverProvider();
if (subEngine != null) {
return subEngine.handle(params);
return subEngine.handle(cancelToken, params);
}
}
//No applicable subEngine...

View File

@@ -10,9 +10,12 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.hover;
import java.util.concurrent.CancellationException;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,13 +60,15 @@ public class VscodeHoverEngineAdapter implements HoverHandler {
}
@Override
public Hover handle(HoverParams params) {
public Hover handle(CancelChecker cancelToken, HoverParams params) {
try {
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.getLatestSnapshot(params.getTextDocument().getUri());
if (doc != null) {
int offset = doc.toOffset(params.getPosition());
cancelToken.checkCanceled();
Tuple2<Renderable, IRegion> hoverTuple = hoverInfoProvider.getHoverInfo(doc, offset);
if (hoverTuple != null) {
@@ -84,6 +89,8 @@ public class VscodeHoverEngineAdapter implements HoverHandler {
} else {
log.debug("No hover because doc is null");
}
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
log.error("error computing hover", e);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2020 Pivotal, Inc.
* Copyright (c) 2016, 2021 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
@@ -12,8 +12,9 @@ package org.springframework.ide.vscode.commons.languageserver.util;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
@FunctionalInterface
public interface HoverHandler {
Hover handle(HoverParams params);
Hover handle(CancelChecker cancelToken, HoverParams params);
}

View File

@@ -57,6 +57,7 @@ import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.CompletableFutures;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClient;
@@ -284,7 +285,7 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
log.debug("hover requested for {}", hoverParams.getPosition());
return CompletableFutures.computeAsync(cancelToken -> {
return computeHover(hoverParams);
return computeHover(cancelToken, hoverParams);
});
@@ -296,12 +297,13 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
// }));
}
private Hover computeHover(HoverParams hoverParams) {
private Hover computeHover(CancelChecker cancelToken, HoverParams hoverParams) {
try {
log.debug("hover handler starting");
HoverHandler h = hoverHandler;
if (h != null) {
return hoverHandler.handle(hoverParams);
cancelToken.checkCanceled();
return hoverHandler.handle(cancelToken, hoverParams);
}
log.debug("no hover because there is no handler");
return null;

View File

@@ -17,17 +17,14 @@ import javax.annotation.PostConstruct;
import org.eclipse.lsp4j.CompletionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
@@ -37,9 +34,8 @@ import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngi
import org.springframework.ide.vscode.commons.yaml.hover.YamlHoverInfoProvider;
import org.springframework.ide.vscode.commons.yaml.quickfix.YamlQuickfixes;
import org.springframework.ide.vscode.commons.yaml.reconcile.ASTTypeCache;
import org.springframework.ide.vscode.commons.yaml.reconcile.TypeBasedYamlSymbolHandler;
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaBasedReconcileEngine;
import org.springframework.ide.vscode.commons.yaml.reconcile.TypeBasedYamlHierarchicalSymbolHandler.HierarchicalDefType;
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaBasedReconcileEngine;
import org.springframework.ide.vscode.commons.yaml.schema.YType;
import org.springframework.ide.vscode.commons.yaml.schema.YamlSchema;
import org.springframework.ide.vscode.commons.yaml.snippet.SchemaBasedSnippetGenerator;
@@ -156,16 +152,16 @@ public class ConcourseLanguageServerInitializer {
server.completionResolver.resolveNow(item);
return item;
});
documents.onHover(params -> {
documents.onHover((cancelToken, params) -> {
log.debug("Concourse hover handler starting");
try {
TextDocument doc = documents.getLatestSnapshot(params);
if (doc != null) {
LanguageId languageId = doc.getLanguageId();
if (LanguageId.CONCOURSE_PIPELINE.equals(doc.getLanguageId())) {
return forPipelines.hoverEngine.handle(params);
return forPipelines.hoverEngine.handle(cancelToken, params);
} else if (LanguageId.CONCOURSE_TASK.equals(doc.getLanguageId())) {
return forTasks.hoverEngine.handle(params);
return forTasks.hoverEngine.handle(cancelToken, params);
} else {
log.debug("No hovers because language-id = {}", languageId);
}

View File

@@ -31,6 +31,7 @@ import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,7 +72,7 @@ public class BootJavaHoverProvider implements HoverHandler {
}
@Override
public Hover handle(HoverParams params) {
public Hover handle(CancelChecker cancelToken, HoverParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.getLatestSnapshot(params);
@@ -80,7 +81,7 @@ public class BootJavaHoverProvider implements HoverHandler {
if (server.getInterestingLanguages().contains(doc.getLanguageId())) {
try {
int offset = doc.toOffset(params.getPosition());
Hover hoverResult = provideHover(doc, offset);
Hover hoverResult = provideHover(cancelToken, doc, offset);
if (hoverResult != null) {
return hoverResult;
}
@@ -205,15 +206,20 @@ public class BootJavaHoverProvider implements HoverHandler {
}
}
private Hover provideHover(TextDocument document, int offset) throws Exception {
private Hover provideHover(CancelChecker cancelToken, TextDocument document, int offset) throws Exception {
final SpringProcessLiveData[] processLiveData = this.liveDataProvider.getLatestLiveData();
cancelToken.checkCanceled();
IJavaProject project = getProject(document).orElse(null);
if (project != null) {
return server.getCompilationUnitCache().withCompilationUnit(project, URI.create(document.getUri()), cu -> {
cancelToken.checkCanceled();
ASTNode node = NodeFinder.perform(cu, offset, 0);
if (node != null) {
return provideHover(node, offset, document, project, processLiveData);
return provideHover(cancelToken, node, offset, document, project, processLiveData);
}
return null;
});
@@ -221,7 +227,7 @@ public class BootJavaHoverProvider implements HoverHandler {
return null;
}
private Hover provideHover(ASTNode node, int offset, TextDocument doc, IJavaProject project, SpringProcessLiveData[] processLiveData) {
private Hover provideHover(CancelChecker cancelToken, ASTNode node, int offset, TextDocument doc, IJavaProject project, SpringProcessLiveData[] processLiveData) {
// look for spring annotations first
ASTNode annotationNode = node;
@@ -229,27 +235,30 @@ public class BootJavaHoverProvider implements HoverHandler {
annotationNode = annotationNode.getParent();
}
if (annotationNode != null) {
return provideHoverForAnnotation(node, (Annotation) annotationNode, offset, doc, project, processLiveData);
return provideHoverForAnnotation(cancelToken, node, (Annotation) annotationNode, offset, doc, project, processLiveData);
}
// then do additional AST node coverage
if (node instanceof SimpleName) {
ASTNode parent = node.getParent();
if (parent instanceof TypeDeclaration) {
return provideHoverForTypeDeclaration(node, (TypeDeclaration) parent, offset, doc, project, processLiveData);
return provideHoverForTypeDeclaration(cancelToken, node, (TypeDeclaration) parent, offset, doc, project, processLiveData);
} else if (parent instanceof MethodDeclaration) {
return provideHoverForMethodDeclaration((MethodDeclaration) parent, offset, doc, project, processLiveData);
return provideHoverForMethodDeclaration(cancelToken, (MethodDeclaration) parent, offset, doc, project, processLiveData);
} else if (parent instanceof SingleVariableDeclaration && parent.getParent() instanceof MethodDeclaration) {
return provideHoverForMethodParameter((SingleVariableDeclaration) parent, offset, doc, project, processLiveData);
return provideHoverForMethodParameter(cancelToken, (SingleVariableDeclaration) parent, offset, doc, project, processLiveData);
}
}
return null;
}
private Hover provideHoverForMethodParameter(SingleVariableDeclaration parameter, int offset, TextDocument doc,
private Hover provideHoverForMethodParameter(CancelChecker cancelToken, SingleVariableDeclaration parameter, int offset, TextDocument doc,
IJavaProject project, SpringProcessLiveData[] processLiveData) {
if (processLiveData.length > 0) {
for (HoverProvider provider : this.hoverProviders.getAll()) {
cancelToken.checkCanceled();
Hover hover = provider.provideMethodParameterHover(parameter, offset, doc, project, processLiveData);
if (hover != null) {
return hover;
@@ -259,10 +268,13 @@ public class BootJavaHoverProvider implements HoverHandler {
return null;
}
private Hover provideHoverForMethodDeclaration(MethodDeclaration methodDeclaration, int offset, TextDocument doc,
private Hover provideHoverForMethodDeclaration(CancelChecker cancelToken, MethodDeclaration methodDeclaration, int offset, TextDocument doc,
IJavaProject project, SpringProcessLiveData[] processLiveData) {
if (processLiveData.length > 0) {
for (HoverProvider provider : this.hoverProviders.getAll()) {
cancelToken.checkCanceled();
Hover hover = provider.provideHover(methodDeclaration, offset, doc, project, processLiveData);
if (hover != null) {
//TODO: compose multiple hovers somehow instead of just returning the first one?
@@ -273,7 +285,7 @@ public class BootJavaHoverProvider implements HoverHandler {
return null;
}
private Hover provideHoverForAnnotation(ASTNode exactNode, Annotation annotation, int offset, TextDocument doc, IJavaProject project,
private Hover provideHoverForAnnotation(CancelChecker cancelToken, ASTNode exactNode, Annotation annotation, int offset, TextDocument doc, IJavaProject project,
SpringProcessLiveData[] processLiveData) {
ITypeBinding type = annotation.resolveTypeBinding();
if (type != null) {
@@ -282,6 +294,9 @@ public class BootJavaHoverProvider implements HoverHandler {
if (processLiveData.length > 0) {
for (HoverProvider provider : this.hoverProviders.get(type)) {
cancelToken.checkCanceled();
Hover hover = provider.provideHover(exactNode, annotation, type, offset, doc, project, processLiveData);
if (hover != null) {
logger.debug("Hover found: "+hover);
@@ -303,12 +318,15 @@ public class BootJavaHoverProvider implements HoverHandler {
return null;
}
private Hover provideHoverForTypeDeclaration(ASTNode exactNode, TypeDeclaration typeDeclaration, int offset, TextDocument doc,
private Hover provideHoverForTypeDeclaration(CancelChecker cancelToken, ASTNode exactNode, TypeDeclaration typeDeclaration, int offset, TextDocument doc,
IJavaProject project, SpringProcessLiveData[] processLiveData) {
if (processLiveData.length > 0) {
ITypeBinding type = typeDeclaration.resolveBinding();
for (HoverProvider provider : this.hoverProviders.getAll()) {
cancelToken.checkCanceled();
Hover hover = provider.provideHover(exactNode, typeDeclaration, type, offset, doc, project, processLiveData);
if (hover!=null) {
//TODO: compose multiple hovers somehow instead of just returning the first one?

View File

@@ -16,6 +16,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@@ -193,6 +194,9 @@ public final class CompilationUnitCache implements DocumentContentProvider {
logger.info("CU Cache: start work on AST for {}", uri.toString());
return requestor.apply(cu);
}
catch (CancellationException e) {
throw e;
}
catch (Exception e) {
logger.error("", e);
}